home *** CD-ROM | disk | FTP | other *** search
/ Maclife 157 / MACLIFE157-2001-09.ISO.7z / MACLIFE157-2001-09.ISO / Linux / MacOS Tools / Other / BootX 1.1.3 (for Old Mac OS) / Sources / src / BootX.c < prev    next >
C/C++ Source or Header  |  2001-07-23  |  70KB  |  2,794 lines

  1. /* BootX
  2.  *
  3.  * Written by Benjamin Herrenschmidt
  4.  *
  5.  * portions of this code from InfiniteOS boot loader by <...>, portions from
  6.  * quik by Paul Mackerras.
  7.  *
  8.  * GPL....
  9.  *
  10.  *
  11.  * To do:
  12.  *
  13.  * - Add menu for pre-configured settings
  14.  */
  15.  
  16. #include <Devices.h>
  17. #include <Files.h>
  18. #include <DriverServices.h>
  19. #include <PEFBinaryFormat.h>
  20. #include <ShutDown.h>
  21. #include <Dialogs.h>
  22. #include <Windows.h>
  23. #include <Menus.h>
  24. #include <LowMem.h>
  25. #include <DiskInit.h>
  26. #include <Processes.h>
  27. #include <TextUtils.h>
  28. #include <Resources.h>
  29. #include <AppleEvents.h>
  30. #include <AEDataModel.h>
  31. #include <Folders.h>
  32. #include <ToolUtils.h>
  33. #include <SCSI.h>
  34. #include <Gestalt.h>
  35. #include <Packages.h>
  36.  
  37. #include <stdio.h>
  38. #include <string.h>
  39. #include <stdlib.h>
  40. #include <stdarg.h>
  41.  
  42. #ifndef macintosh
  43. #define macintosh
  44. #endif
  45.  
  46. #ifndef BOOTX_BUILD_INIT
  47. #define BOOTX_BUILD_INIT                0
  48. #endif
  49.  
  50. /* BootX trace is not supported in this version */
  51. #ifndef BOOTX_TRACE
  52. #define BOOTX_TRACE                    0
  53. #endif
  54.  
  55. #ifndef BOOTX_LOG_MAP
  56. #define BOOTX_LOG_MAP                    0
  57. #endif
  58.  
  59. /* This option reverts to old bootx behaviour: the kernel is entered
  60.    directly, without turnig OFF the MMU. */
  61. #ifndef NO_BOOTSTRAP
  62. #define NO_BOOTSTRAP                    0
  63. #endif
  64.  
  65. #include "BootX.h"
  66. #include "DeviceTree.h"
  67. #include "LowLevelBoot.h"
  68. #include "ErrorCodes.h"
  69.  
  70. #include "elf_loader_defs.h"
  71.  
  72. #include "MoreFiles.h"
  73. #include "MoreFilesExtras.h"
  74. #include "IterateDirectory.h"
  75.  
  76. #ifndef TRUE
  77. #define TRUE    1
  78. #define FALSE    0
  79. #endif
  80.  
  81. #define NAME_REGISTRY_MAX_SIZE        (200UL * 1024UL)            // 200Kb: Size pre-allocated for holding name registry
  82. #define BOOT_KERNEL_STACK_SIZE        65536                        // initial stack
  83.  
  84. #define PAGE_ALIGN(x)    ((((UInt32)(x)) + g_page_size - 1) & (-g_page_size))
  85. #define LINE_ALIGN(x)    ((((UInt32)(x)) + 32 - 1) & (-32))
  86. #define BI_OFFSET(x)    (g_stuff_offsets[x] - g_stuff_offsets[offset_bootinfo])
  87.     
  88. /* Indexes in offset array */
  89. enum
  90. {
  91.     offset_kernel = 0,    /* kernel itself, offset 0 */
  92.     offset_stack,        /* boot stack */
  93.     offset_bootinfo,    /* boot_info */
  94.     offset_arguments,    /* args line */
  95.     offset_color_map,    /* colormap setup by bootx */
  96.     offset_device_tree,    /* device tree */
  97.     offset_ramdisk,        /* optional ramdisk */
  98.     offset_unmangler,    /* unmangler (may be moved higher) */
  99.     offset_count
  100. };
  101.  
  102.  
  103. #define DEBUG_ERR(err,msg)            display_error((err), msg, __FILE__, __LINE__)
  104.  
  105. #if BOOTX_LOG_MAP
  106. static void        open_log_file(void);
  107. static void        close_log_file(void);
  108. static void        log_printf(const char *fmt, ...);
  109. #endif
  110.  
  111.  
  112. #if BOOTX_BUILD_INIT
  113. /* Procinfo of entry point */
  114. ProcInfoType __procinfo = kPascalStackBased;
  115. #endif
  116.  
  117. /* Dialog items IDs */
  118. enum
  119. {
  120.     button_boot_linux        = 2,
  121.     button_boot_macos        = 3,
  122.     field_kernel_args        = 5,
  123.     field_root_device        = 6,
  124.     button_set_default        = 7,
  125.     text_status_display        = 9,
  126.     check_use_ram_disk        = 11,
  127.     check_video_of_only        = 12,
  128.     button_boot_mklinux        = 15,
  129.     check_set_l2cr            = 16,
  130.     menu_kernels            = 17
  131. };
  132.  
  133. /* Resources */
  134. enum
  135. {
  136.     string_kernel_names        = 128,
  137.     string_ramdisk_names    = 129,
  138.     string_kernel_args        = 130,
  139.     string_prefs_file_names    = 131,
  140.     string_boot_delay        = 132,
  141.     string_mkboot_names        = 133,
  142.     string_mkboot_patch        = 134,
  143.     string_kernel_folder    = 135,
  144.     
  145.     string_mkboot_patched    = 257,
  146.     
  147.     text_mkboot_fake_prefs    = 128,
  148.  
  149.     dialog_main                = 131,
  150.     alert_error                = 130,
  151.     
  152.     code_boot_glue68k        = 128,
  153.     code_boot_gluePPC        = 129,
  154.     
  155.     menu_kernel_list        = 1000
  156. };
  157.  
  158. /* Boot choice */
  159. enum
  160. {
  161.     boot_macos    = 0,
  162.     boot_linux,
  163.     boot_mklinux,
  164.     
  165.     boot_choice_count = 3
  166. };
  167.  
  168. static short g_boot_choices[boot_choice_count][2] = 
  169. {
  170.     button_boot_macos    , 1,
  171.     button_boot_linux    , 0,
  172.     button_boot_mklinux    , 0
  173. };
  174.  
  175.  
  176. /* Struct used for mount event queue */
  177. typedef struct saved_mount
  178. {
  179.     QElem    link;
  180.     UInt32    message;
  181.     
  182. } saved_mount_t;
  183.  
  184. /* An item in the kernel list. Note that an empty name
  185.    means a separator item */
  186. typedef struct kernel_item
  187. {
  188.     FSSpec    file;
  189.     short    menu_item;
  190.     UInt32    file_size;
  191.     UInt32    offset;
  192.     UInt32    mem_size;
  193.     UInt32    entry;
  194.     short    file_ref;
  195.     
  196. } kernel_item_t;
  197.  
  198. #define MAX_KERNEL_ITEMS    32
  199.  
  200. /* MacOS nanokernel data structures */
  201. #define MACOS_MEMMAP_PTR_ADDR        0x5FFFEFF0    
  202. #define MACOS_MEMMAP_SIZE_ADDR        0x5FFFEFF6    
  203. #define MACOS_MEMMAP_BANK_0FFSET    48
  204.  
  205.  
  206. /* Preferences */
  207.  
  208. #define BOOTX_PREFS_VERSION                4
  209. #define BOOTX_PREFS_COMPATIBLE_VERSION    1
  210.  
  211. #pragma options align=power
  212. typedef struct bootx_prefs
  213. {
  214.     /* Version of this structure */
  215.     unsigned long    version;
  216.     /* backward compatible down to version: */
  217.     unsigned long    compatible_version;
  218.  
  219.     unsigned char    boot_choice;    // uchar for compatibility
  220.     Boolean            use_ramdisk;
  221.     Boolean            video_of_only;
  222.     Boolean            use_l2cr_settings;
  223.     Boolean            unused_boolean[4];
  224.     Str255            command_line;
  225.     Str32            root_device;
  226.     Str63            kernel_name;
  227.     
  228. } bootx_prefs, **bootx_prefs_handle;
  229. #pragma options align=reset
  230.  
  231. /* Generic tools */
  232. inline void
  233. pstrcpy(Str255 dst, ConstStr255Param src)
  234. {
  235.     memcpy(dst, src, src[0] + 1);
  236. }
  237.  
  238. inline void
  239. pstrncpy(Str255 dst, ConstStr255Param src, unsigned long max_size)
  240. {
  241.     unsigned char l = (src[0] > max_size) ?
  242.     max_size : src[0]; memcpy(dst, src, l+1);
  243.     dst[0] = l;
  244. }
  245.  
  246. inline void
  247. pstrcat(Str255 dst, ConstStr255Param append)
  248. {
  249.     int size = append[0];
  250.     
  251.     if ((dst[0] + size) > 255)
  252.         size = 255 - dst[0];
  253.         
  254.     memcpy(&dst[dst[0]+1], &append[1], size);
  255.     
  256.     dst[0] += size;
  257. }
  258.  
  259. /* --- Prototypes -------------------------------------- */
  260.  
  261. typedef void (*iterate_device_proc)(RegEntryIDPtr entryID);
  262.  
  263. pascal void            main(void);
  264.  
  265. static OSErr        make_resident(void* ptr, unsigned long size, Boolean contiguous);
  266. static UInt8*        get_physical(void* ptr);
  267. static OSErr        check_kernel(kernel_item_t*    kern_infos, Boolean will_load);
  268. static void*        load_bootstrap(long mapsize, UInt32** outMapBegin, UInt32 *outTotalSize);
  269. static OSErr        load_kernel(kernel_item_t* kern_infos, UInt8* loc);
  270. static UInt32        get_temp_page(UInt32 *cur_temp, UInt32 *used_map, UInt32 used_size);
  271. static OSErr        make_kernel_map(UInt32 **out_map, UInt32 *out_size);
  272. static void            init_macos_toolbox(void);
  273. static Boolean        create_dialog(void);
  274. static void            dispose_dialog(void);
  275. static void            prepare_and_boot(kernel_item_t* kern_infos);
  276. static Boolean        locate_ramdisk(void);
  277. static void            setup_default_buttons(void);
  278. static void            display_error(OSErr err, int msg, char *file, int line);
  279. static void            get_options_from_dialog(void);
  280. static OSErr        open_ramdisk(FSSpec *ramdiskSpec);
  281. static OSErr        load_ramdisk(UInt8* loc);
  282. static OSErr        locate_file(short namesResourceID, OSType defaultFolder, FSSpecPtr outSpec);
  283. static void            load_prefs(void);
  284. static void            save_prefs(void);
  285. static void            do_boot_mklinux(void);
  286. static Boolean        locate_mklinux(void);
  287. static OSErr        build_pci_device_tree(Ptr* outDevTree, UInt32 *outDevTreeSize, UInt32 *outDispRegOff);
  288. static void            build_memory_map(void);
  289. static void            lookup_kernels(void);
  290. static pascal void    kernel_iterate_filter_proc(    const CInfoPBRec*    const cpbPtr,
  291.                                                 Boolean                *quitFlag,
  292.                                                 void*                yourDataPtr);
  293. static void            build_kernels_menu(void);
  294. static void            add_l2cr_property(UInt32 l2cr_value);
  295. static void            check_burgundy_patch(void);
  296.  
  297.  
  298. #if !BOOTX_BUILD_INIT
  299. static OSErr        send_restart_to_finder(void);
  300. static OSErr        find_finder_process(ProcessSerialNumberPtr processSN);
  301. #else
  302. static Ptr            alloc_high_mem(unsigned long count);
  303. static void            save_mount_event(EventRecord *event);
  304. static void            resend_mount_events(void);
  305. #endif
  306.  
  307. // CFM stuffs
  308. pascal OSErr        FragmentInitialize(const CFragInitBlockPtr initInfo);
  309. pascal void            FragmentTerminate(void);
  310. pascal OSErr        __initialize(const CFragInitBlockPtr initInfo);
  311. pascal void            __terminate(void);
  312.  
  313.  
  314. /* --- Globals ----------------------------------------- */
  315.  
  316.  
  317. static UInt8*                                g_stuff;
  318. static Ptr                                    g_stuff_ptr;
  319. static UInt32                                g_stuff_offsets[offset_count];
  320. static boot_infos_t*                        g_boot_infos;
  321. static Boolean                                g_use_ramdisk;
  322. static ControlHandle                        g_use_ramdisk_cntl;
  323. static void*                                g_ramdisk;
  324. static UInt32                                g_ramdisk_size;
  325. static short                                g_ramdisk_ref;
  326. static Boolean                                g_video_of_only;
  327. static ControlHandle                        g_video_of_only_cntl;
  328. static DialogPtr                            g_dialog;
  329. static Str255                                g_kernel_args;
  330. static THz                                    g_my_zone;
  331. static FSSpec                                g_kernel_spec;
  332. static FSSpec                                g_ramdisk_spec;
  333. static FSSpec                                g_mkboot_spec;
  334. static Boolean                                g_have_ramdisk;
  335. static int                                    g_current_choice;
  336. static UInt32                                g_entry_ticks;
  337. static UInt32                                g_autoboot_delay;
  338. static Handle                                g_status_item;
  339. static QHdr                                    g_mount_queue;
  340. static Boolean                                g_vm_present;
  341. static UInt32                                g_page_size;
  342. static Boolean                                g_L2CR_pref;
  343. static Boolean                                g_L2CR_set;
  344. static Boolean                                g_L2CR_available;
  345. static UInt32                                g_L2CR_value;
  346. static ControlHandle                        g_set_L2CR_cntl;
  347. static Boolean                                g_arch_PCI;
  348. static UInt32                                g_load_base = 0;
  349. static ControlHandle                        g_kernel_menu = NULL;
  350. static kernel_item_t                        g_kernel_items[MAX_KERNEL_ITEMS];
  351. static UInt32                                g_kernel_items_count = 0;
  352. static UInt32                                g_kernel_items_choice = 0;
  353.  
  354. #if !BOOTX_BUILD_INIT
  355. static FSSpec                                g_application_spec;
  356. #endif
  357.  
  358. static RGBColor                                g_back_color = {0xEEEE, 0xEEEE, 0xEEEE};
  359.  
  360. /* --- Implementation ---------------------------------- */
  361.  
  362. /* Pre-initialize */
  363. pascal OSErr
  364. FragmentInitialize(const CFragInitBlockPtr /*initInfo*/)
  365. {
  366. // -- Not needed if we don't use C++
  367. //    OSErr    err = __initialize(initInfo);
  368. //    if (err != noErr)
  369. //        return err;
  370. //
  371. //    g_my_connection_ID = (CFragConnectionID)initInfo->connectionID;
  372. //
  373. //
  374. //    SetDriverClosureMemory(initInfo->closureID, true);
  375.  
  376.     return noErr;
  377. }
  378.  
  379. pascal void
  380. FragmentTerminate(void)
  381. {
  382. // -- Not needed if we don't use C++
  383. //    __terminate();
  384.  
  385. //    DebugStr("¥pFrag term");
  386. }
  387.  
  388.  
  389. /* Initialize MacOS managers */
  390. void
  391. init_macos_toolbox(void)
  392. {
  393. #if !BOOTX_BUILD_INIT
  394.     OSErr                err;
  395.     ProcessInfoRec        infos;
  396.     ProcessSerialNumber    me;
  397.     Str255                my_name;
  398. #endif
  399.  
  400.     InitGraf(&qd.thePort);
  401.     InitFonts();
  402.     InitWindows();
  403. #if BOOTX_BUILD_INIT
  404.     InitMenus();
  405. #endif    
  406.     TEInit();
  407.     InitDialogs(nil);
  408. #if BOOTX_BUILD_INIT
  409.     InitAllPacks();
  410. #endif    
  411.     InitCursor();
  412. #if BOOTX_BUILD_INIT
  413.     LMSetDeskHook(NULL);
  414.     LMSetDragHook(NULL);
  415.     LMSetGhostWindow(NULL);
  416.     TextFont(0);
  417.     TextSize(12);
  418.     DrawMenuBar();
  419. #endif
  420.     
  421. #if BOOTX_BUILD_INIT
  422.     MoreMasters();
  423. #else
  424.     MaxApplZone();
  425.     MoreMasters();
  426.     MoreMasters();
  427.     MoreMasters();
  428.     MoreMasters();
  429.  
  430.     FlushEvents(everyEvent, 0);
  431.  
  432.     err = GetCurrentProcess(&me);
  433.     if (err != noErr) {
  434.         DEBUG_ERR(err, error_get_current_process);
  435.         ExitToShell();
  436.     }
  437.  
  438.     memset(&infos, 0, sizeof(ProcessInfoRec));
  439.     infos.processInfoLength        = sizeof(ProcessInfoRec);
  440.     infos.processName            = my_name;
  441.     infos.processAppSpec        = &g_application_spec;
  442.     err = GetProcessInformation(&me, &infos);
  443.     if (err != noErr)
  444.     {
  445.         DEBUG_ERR(err, error_get_process_infos);
  446.         ExitToShell();
  447.     }    
  448. #endif
  449. }
  450.  
  451. /* Create the dialog, setup initial values, and gather infos about some
  452.  * of the items for later use.
  453.  */
  454. Boolean
  455. create_dialog()
  456. {
  457.     DialogPeek                dp;
  458.     short                    itemType;
  459.     Rect                    itemBox;
  460.     Handle                    itemHandle;
  461.     FontInfo                theFontInfo;
  462.     
  463.     g_dialog = GetNewDialog(dialog_main, NULL, (WindowPtr)-1);
  464.     if (!g_dialog)
  465.     {
  466.         DEBUG_ERR(0, error_create_dialog);
  467.         return false;
  468.     }
  469.     SetPort(g_dialog);
  470.     
  471.     dp = (DialogPeek)g_dialog;
  472.     TextFont((**(dp->textH)).txFont = 3);
  473.     TextSize((**(dp->textH)).txSize = 9);
  474.     TextFace((**(dp->textH)).txFace = 0);
  475.     GetFontInfo(&theFontInfo);
  476.     (**(dp->textH)).lineHeight = theFontInfo.ascent + theFontInfo.descent + theFontInfo.leading;
  477.     (**(dp->textH)).fontAscent = theFontInfo.ascent;
  478.  
  479.     GetDialogItem(g_dialog, text_status_display, &itemType, &g_status_item, &itemBox) ;
  480.  
  481.     GetDialogItem(g_dialog, button_boot_linux, &itemType, &itemHandle, &itemBox) ;
  482.     if (!g_boot_choices[boot_linux][1])
  483.         HiliteControl((ControlHandle)itemHandle, 255);
  484.     GetDialogItem(g_dialog, button_boot_mklinux, &itemType, &itemHandle, &itemBox) ;
  485. #if BOOTX_BUILD_INIT
  486.     if (!g_boot_choices[boot_mklinux][1])
  487.         HiliteControl((ControlHandle)itemHandle, 255);
  488. #else
  489.     HideDialogItem(g_dialog, button_boot_mklinux);
  490. #endif
  491.     GetDialogItem(g_dialog, check_use_ram_disk, &itemType, (Handle *)&g_use_ramdisk_cntl, &itemBox) ;
  492.     GetDialogItem(g_dialog, check_video_of_only, &itemType, (Handle *)&g_video_of_only_cntl, &itemBox) ;
  493.  
  494.     GetDialogItem(g_dialog, check_set_l2cr, &itemType, (Handle *)&g_set_L2CR_cntl, &itemBox);
  495.     if (!g_L2CR_available)
  496.         HideDialogItem(g_dialog, check_set_l2cr);
  497.  
  498.     SetDialogTracksCursor(g_dialog, true);
  499.     
  500.     SetControlValue(g_use_ramdisk_cntl, g_use_ramdisk);
  501.     
  502.     RGBBackColor(&g_back_color);
  503.     
  504.     GetDialogItem(g_dialog, menu_kernels, &itemType, (Handle *)&g_kernel_menu, &itemBox);
  505.     
  506.     return true;
  507. }
  508.  
  509. void
  510. get_options_from_dialog(void)
  511. {
  512.     short                itemType;
  513.     Rect                itemBox;
  514.     Handle                itemHandle;
  515.     Str255                tempStr;
  516.     int                    i;
  517.     
  518.     tempStr[0] = 0;
  519.     g_kernel_args[0] = 0;
  520.     
  521.     if (!g_use_ramdisk)
  522.     {
  523.         GetDialogItem(g_dialog, field_root_device, &itemType, &itemHandle, &itemBox);
  524.         if (itemHandle)
  525.             GetDialogItemText(itemHandle, tempStr);
  526.         if (tempStr[0])
  527.         {
  528.             pstrcpy(g_kernel_args, "¥proot=/dev/");
  529.             pstrcat(g_kernel_args, tempStr);
  530.         }
  531.     }
  532.  
  533.     tempStr[0] = 0;
  534.     GetDialogItem(g_dialog, field_kernel_args, &itemType, &itemHandle, &itemBox);
  535.     if (itemHandle)
  536.         GetDialogItemText(itemHandle, tempStr);
  537.     if (tempStr[0])
  538.     {
  539.         if (g_kernel_args[0])
  540.             pstrcat(g_kernel_args, "¥p ");
  541.         pstrcat(g_kernel_args, tempStr);
  542.     }
  543.  
  544.     // Eventually update kernel args for ofonly mode
  545.     if (g_video_of_only)
  546.     {
  547.         if (g_kernel_args[0])
  548.             pstrcat(g_kernel_args, "¥p ");
  549.         pstrcat(g_kernel_args, "¥pvideo=ofonly");
  550.     }
  551.  
  552.     // Get selected kernel
  553.     g_kernel_items_choice = 0;
  554.     for (i=0; i<g_kernel_items_count; i++)
  555.         if (g_kernel_items[i].menu_item == GetControlValue(g_kernel_menu))
  556.             g_kernel_items_choice = i;
  557. }
  558.  
  559. /* I'll let you guess what this function does ;-)
  560.  */
  561. void
  562. dispose_dialog()
  563. {
  564.     Boolean    hasEvent;
  565.     
  566.     /* Flush any pending update event */
  567.     do {
  568.         EventRecord     event;
  569.         
  570.         hasEvent = WaitNextEvent(everyEvent & (~diskMask), &event, 1, NULL);
  571.         if (hasEvent && (event.what == updateEvt)) {
  572.             SetPort((WindowPtr)event.message);
  573.             BeginUpdate((WindowPtr)event.message);
  574.             EndUpdate((WindowPtr)event.message);
  575.         }
  576.     } while(hasEvent);
  577.     
  578.     /* Get rid of the dialog */
  579.     DisposeDialog(g_dialog);
  580.     g_dialog = NULL;
  581. }
  582.  
  583. void
  584. setup_default_buttons(void)
  585. {
  586.     Rect        r_erase, r_fill;
  587.     RgnHandle    erase_rgn, rgn1, rgn2;
  588.     PenState    state;
  589.     short        button, i;
  590.     short        itemType;
  591.     Handle        itemHandle;
  592.     
  593.     SetPort(g_dialog);
  594.     
  595.     button = g_boot_choices[g_current_choice][0];
  596.     SetDialogDefaultItem(g_dialog, button);
  597.     SetDialogCancelItem(g_dialog, button_boot_macos);
  598.  
  599.     erase_rgn = NewRgn();
  600.     rgn1 = NewRgn();
  601.     rgn2 = NewRgn();
  602.     
  603.     for (i=0; i<boot_choice_count; i++)
  604.         if (i == g_current_choice)
  605.             GetDialogItem(g_dialog, g_boot_choices[i][0], &itemType, &itemHandle, &r_fill) ;
  606.         else
  607.         {
  608.             GetDialogItem(g_dialog, g_boot_choices[i][0], &itemType, &itemHandle, &r_erase);
  609.             RectRgn(rgn1, &r_erase);
  610.             InsetRect(&r_erase, -4, -4);
  611.             RectRgn(rgn2, &r_erase);
  612.             DiffRgn(rgn2, rgn1, rgn1);
  613.             UnionRgn(rgn1, erase_rgn, erase_rgn);
  614.         }
  615.  
  616.     /* We still do the erasing & drawing of the default outline
  617.        since some versions of the default filter proc will not handle
  618.        correctly the dynamic changing. Appearance Manager patches
  619.        FrameRoundRect so this won't harm. Under MacOS 8.1, the Appearance
  620.        won't be available so early during boot. Under 8.5, things seems to be
  621.        different and you'll get the AM look at startup.
  622.      */
  623.     GetPenState(&state);
  624.     PenNormal();
  625.     PenSize(3,3);
  626.     InsetRect(&r_fill, -4, -4);
  627.     EraseRgn(erase_rgn);    
  628.     FrameRoundRect(&r_fill, 16, 16);
  629.     SetPenState(&state);
  630.     
  631.     DisposeRgn(rgn1);
  632.     DisposeRgn(rgn2);
  633.     DisposeRgn(erase_rgn);
  634. }
  635.  
  636. #if BOOTX_BUILD_INIT
  637.  
  638. /* This function allocates memory by moving down the BufPtr low memory globals. This
  639.  * is a special technique for use _only_ by system extensions that need a large amount
  640.  * that won't be available in the system heap. That's our case. The strange formula
  641.  * we use with MemTop comes from the MacOS historical roots, the system will make sure
  642.  * that MemTop has a correct value for this formula to apply.
  643.  * Note that this memory will be pageable.
  644.  */
  645. Ptr
  646. alloc_high_mem(unsigned long count)
  647. {
  648.     Ptr limit = (Ptr)((UInt32)LMGetMemTop()/2 + 1024);
  649.     Ptr bufPtr = LMGetBufPtr();
  650.     
  651.     count += 256;
  652.     
  653.     if ((bufPtr - limit) < count)
  654.         return NULL;
  655.     
  656.     LMSetBufPtr(bufPtr - count);
  657.     
  658.     bufPtr -= count;
  659.     
  660.     return (Ptr)(((UInt32)bufPtr | 0xFFUL) + 1);
  661. }
  662.  
  663. #endif
  664.  
  665.  
  666. OSErr
  667. locate_file(short namesResourceID, OSType defaultFolder, FSSpecPtr outSpec)
  668. {
  669.     int                i;
  670.     OSErr            err;
  671.     short            defaultVRefNum;
  672.     long            defaultParID;
  673.     static Str255    fileName;
  674. #if !BOOTX_BUILD_INIT
  675.     Boolean            tryApp;
  676. #endif
  677.  
  678.     // Build kernel FSSpec
  679.     err = FindFolder(    kOnSystemDisk,
  680.                         defaultFolder,
  681.                         false,
  682.                         &defaultVRefNum,
  683.                         &defaultParID);
  684.     if (err != noErr)
  685.         return err;
  686.  
  687.     i=1;
  688. #if !BOOTX_BUILD_INIT
  689.     tryApp = true;
  690. #endif    
  691.  
  692.     do
  693.     {
  694.         GetIndString(fileName, namesResourceID, i);
  695.         if (fileName[0] == 0)
  696.         {
  697. #if !BOOTX_BUILD_INIT
  698.             if (tryApp)
  699.             {
  700.                 tryApp = false;
  701.                 i = 1;
  702.                 continue;
  703.             }
  704. #endif            
  705.             return fnfErr;
  706.         }
  707.         
  708. #if BOOTX_BUILD_INIT
  709.         err = FSMakeFSSpec(    defaultVRefNum, defaultParID, fileName, outSpec);
  710. #else
  711.         err = FSMakeFSSpec(    tryApp ? g_application_spec.vRefNum : defaultVRefNum,
  712.                             tryApp ? g_application_spec.parID : defaultParID,
  713.                             fileName,
  714.                             outSpec);
  715. #endif
  716.         if (err == noErr)
  717.         {
  718.             Boolean wasFolder;
  719.             Boolean wasAlias;
  720.             
  721.             /* Resolve it in case it was an alias - should do it silently however !*/
  722.             ResolveAliasFile(    outSpec,
  723.                                 true,
  724.                                 &wasFolder,
  725.                                 &wasAlias);
  726.             break;
  727.         }
  728.         
  729.         i++;
  730.     } while(true);
  731.     
  732.     return err;
  733. }
  734.  
  735. /* Locate the kernel and the ram disk (optional) files on disk.
  736.  * This function uses a looks for them first next to the BootX application,
  737.  * then in the system folder's root.
  738.  * For each file, all possible names are tested. The names are stored inside
  739.  * BootX resources STR#, ID 128 for kernel names, ID 129 for ramdisk names
  740.  */
  741. Boolean
  742. locate_ramdisk(void)
  743. {
  744.     OSErr            err;
  745.  
  746.     // Lookup ram disk
  747.     g_have_ramdisk = false;
  748.     err = locate_file(string_ramdisk_names, kSystemFolderType, &g_ramdisk_spec);
  749.     if (err != noErr)
  750.         err = locate_file(string_ramdisk_names, kExtensionFolderType, &g_ramdisk_spec);
  751.     if (err == noErr)
  752.         g_have_ramdisk = true;
  753.  
  754.     return true;
  755. }
  756.  
  757. #if BOOTX_BUILD_INIT
  758.  
  759. /* Save bad mount events in our special queue. We repost them later so they can
  760.  * eventually be handled by an external file system that gets loaded after
  761.  * us (like MountX).
  762.  */
  763. void
  764. save_mount_event(EventRecord *event)
  765. {
  766.     saved_mount_t*    stub;
  767.     
  768. static s_save_count = 0;    
  769.     
  770. #if BOOTX_TRACE
  771.     ST_Printf(0,0,"saving mount event, msg: 0x%x, error: 0x%x¥n",
  772.             (int)LoWord(event->message), HiWord(event->message));
  773. #endif                        
  774.  
  775.     if ((++s_save_count) > 32)
  776.     {
  777.         DEBUG_ERR(-666, error_too_many_mounts);
  778.         return;
  779.     }
  780.     stub = (saved_mount_t*)NewPtr(sizeof(saved_mount_t));
  781.     if (stub == NULL)
  782.     {
  783.         DEBUG_ERR(MemError(), error_alloc_event_stub);
  784.         return;
  785.     }
  786.     
  787.     stub->message = event->message;
  788.     
  789.     Enqueue((QElemPtr)stub, &g_mount_queue);
  790. }
  791.  
  792. /* Repost events gathered previously */
  793. void
  794. resend_mount_events(void)
  795. {
  796.     saved_mount_t*    stub;
  797.     Handle            h;
  798.     Boolean            disable;
  799.     Boolean            only_err;
  800.     
  801.     h = GetResource('NOMT', 666);
  802.     disable = (h && (*h) && (**h));
  803.     only_err = (disable && ((**h) == 2));
  804.     if (h)
  805.         ReleaseResource(h);
  806.         
  807.     while(NULL != (stub = (saved_mount_t *)g_mount_queue.qHead))
  808.     {
  809.         if (Dequeue((QElemPtr)stub, &g_mount_queue) == noErr)
  810.         {
  811.             OSErr    eventResult = HiWord(stub->message);
  812.             short    driveNumber = LoWord(stub->message);
  813.             
  814.             if (!disable || 
  815.                 (only_err && ((eventResult == noErr) || (HiWord(stub->message) == volOnLinErr))))
  816.             {
  817. #if BOOTX_TRACE
  818.                 ST_Printf(0,0,"posting event, drive: 0x%x, error was: 0x%x¥n", (int)driveNumber, eventResult);
  819. #endif                        
  820.                 PostEvent(diskEvt, driveNumber);
  821.             }
  822.             DisposePtr((Ptr)stub);
  823.         }
  824.     }
  825. }
  826.  
  827. #endif
  828.  
  829. /* This function looks up possible linux kernel files and fills the
  830.    kernel menu */
  831. void
  832. lookup_kernels(void)
  833. {
  834.     FSSpec    spec, folder_spec, previous;
  835.     Str255    folder_name;
  836.     Boolean    isDir, has_previous;
  837.     long    folder_id, defaultParID;
  838.     short    defaultVRefNum;
  839.     OSErr    err;
  840.     
  841.     // Lookup kernel old way in system folder/application
  842.     has_previous = false;
  843.     err = locate_file(string_kernel_names, kSystemFolderType, &spec);
  844.     if (err == noErr) {
  845.         memset(&g_kernel_items[g_kernel_items_count], 0, sizeof(kernel_item_t));
  846.         g_kernel_items[g_kernel_items_count].file = spec;
  847.         err = check_kernel(&g_kernel_items[g_kernel_items_count], false);
  848.         if (err == noErr) {
  849.             g_kernel_items_count++;
  850.             has_previous = true;
  851.             previous = spec;
  852.         }
  853.     }
  854.     
  855.     // Lookup kernel old way in extensions folder/application
  856.     err = locate_file(string_kernel_names, kExtensionFolderType, &spec);
  857.     if (err == noErr) {
  858.         if (!(has_previous && (spec.vRefNum == previous.vRefNum)
  859.           && (spec.parID == previous.parID)
  860.           && EqualString(spec.name, previous.name, false, false))) {
  861.             memset(&g_kernel_items[g_kernel_items_count], 0, sizeof(kernel_item_t));
  862.             g_kernel_items[g_kernel_items_count].file = spec;
  863.             err = check_kernel(&g_kernel_items[g_kernel_items_count], false);
  864.             if (err == noErr)
  865.                 g_kernel_items_count++;
  866.             }
  867.     }
  868.     
  869.     GetIndString(folder_name, string_kernel_folder, 1);
  870.     
  871.     // Now check for a "Linux Kernels" folder next to BootX (app only)
  872. #if !BOOTX_BUILD_INIT
  873.     err = FSMakeFSSpec(    g_application_spec.vRefNum,
  874.                         g_application_spec.parID,
  875.                         folder_name, &folder_spec);
  876.     if (err == noErr) {
  877.         Boolean wasFolder;
  878.         Boolean wasAlias;
  879.             
  880.         /* Resolve it in case it was an alias - should do it silently however !*/
  881.         ResolveAliasFile(&folder_spec, true, &wasFolder, &wasAlias);
  882.         err = FSpGetDirectoryID(&folder_spec, &folder_id, &isDir);
  883.         if ((err == noErr) && isDir) {
  884.             err = FSpIterateDirectory(    &folder_spec,
  885.                                         1,
  886.                                         kernel_iterate_filter_proc,
  887.                                         NULL);
  888.         }
  889.     }
  890. #endif
  891.  
  892.     // Now check for a "Linux Kernels" folder in the system folder
  893.     // Build kernel FSSpec
  894.     err = FindFolder(    kOnSystemDisk,
  895.                         kSystemFolderType,
  896.                         false,
  897.                         &defaultVRefNum,
  898.                         &defaultParID);
  899.     if (err == noErr) {
  900.         err = FSMakeFSSpec(    defaultVRefNum,
  901.                             defaultParID,
  902.                             folder_name, &folder_spec);
  903.         if (err == noErr) {
  904.             Boolean wasFolder;
  905.             Boolean wasAlias;
  906.             
  907.             /* Resolve it in case it was an alias - should do it silently however !*/
  908.             ResolveAliasFile(&folder_spec, true, &wasFolder, &wasAlias);
  909.             err = FSpGetDirectoryID(&folder_spec, &folder_id, &isDir);
  910.             if ((err == noErr) && isDir) {
  911.                 err = FSpIterateDirectory(    &folder_spec,
  912.                                             1,
  913.                                             kernel_iterate_filter_proc,
  914.                                             NULL);
  915.             }
  916.         }
  917.     }
  918. }  
  919.  
  920. pascal void
  921. kernel_iterate_filter_proc(    const CInfoPBRec*    const cpbPtr,
  922.                             Boolean                *quitFlag,
  923.                             void*                yourDataPtr)
  924. {
  925. #pragma unused (quitFlag,yourDataPtr)
  926.  
  927.     kernel_item_t*    kern_infos = &g_kernel_items[g_kernel_items_count];
  928.     
  929.     memset(kern_infos, 0, sizeof(kernel_item_t));
  930.     pstrcpy(kern_infos->file.name, cpbPtr->hFileInfo.ioNamePtr);
  931.     kern_infos->file.parID = cpbPtr->hFileInfo.ioFlParID;
  932.     kern_infos->file.vRefNum = cpbPtr->hFileInfo.ioVRefNum;
  933.  
  934.     if (check_kernel(kern_infos, false) == noErr) {
  935.         g_kernel_items_count++;
  936.     }
  937. }
  938.  
  939. void
  940. build_kernels_menu(void)
  941. {
  942.     int                        item, i;
  943.     short                    lastVol;
  944.     long                    lastDirID;
  945.     MenuHandle                menu;
  946.     PopupPrivateDataHandle    dataH;
  947.         
  948.     lastDirID    = 0;
  949.     lastVol        = 0;
  950.     item        = 1;
  951.     
  952.     dataH =    (PopupPrivateDataHandle) (**g_kernel_menu).contrlData;
  953.     menu = NULL;
  954.     if (dataH != NULL)
  955.         menu = (**dataH).mHandle;
  956.     if (!menu)
  957.         return;
  958.  
  959.     while(CountMenuItems(menu))
  960.         DeleteMenuItem(menu, 1);
  961.     for (i=0; i<g_kernel_items_count; i++) {
  962.         if ((item > 1) && ((g_kernel_items[i].file.vRefNum != lastVol)
  963.             || (g_kernel_items[i].file.parID != lastDirID))) {
  964.             AppendMenu(menu, "¥p(-");
  965.             item++;
  966.         }
  967.         AppendMenu(menu, "¥p ");
  968.         SetMenuItemText(menu, item, g_kernel_items[i].file.name);
  969.         g_kernel_items[i].menu_item = item;
  970.         item++;
  971.         lastDirID = g_kernel_items[i].file.parID;
  972.         lastVol = g_kernel_items[i].file.vRefNum;
  973.     }
  974.  
  975.     SetControlMinimum(g_kernel_menu, 1);
  976.     SetControlMaximum(g_kernel_menu, item);
  977.     SetControlValue(g_kernel_menu, 1);
  978. }
  979.  
  980. /* Entry point */
  981. pascal void
  982. main(void)
  983. {
  984.     Boolean            finished;
  985.     Boolean            counter_on;
  986.     Boolean            stop_counter;
  987.     Boolean            simulate;
  988.     GrafPtr            oldPort;
  989.     ModalFilterUPP    std_filter;
  990.     UInt32            last_disp_ticks;
  991.     static Str255    tempStr;
  992.     long            response;
  993.     
  994.     /* Silently dies on sheepshaver */
  995.     if (((*(UInt32 *)0x2800)) == 'Baah') {
  996. #if BOOTX_BUILD_INIT
  997.         FragmentTerminate();
  998. #endif
  999.         return;
  1000.     }
  1001.     
  1002.     g_my_zone = GetZone();
  1003.     
  1004. #if BOOTX_TRACE
  1005. #if BOOTX_BUILD_INIT
  1006.     ST_TraceInit("BootX INIT", 1, NULL);
  1007. #else
  1008.     ST_TraceInit("BootX App", 1, NULL);
  1009. #endif
  1010. #endif
  1011.  
  1012.     init_macos_toolbox();
  1013.  
  1014.     g_dialog                = NULL;
  1015.     g_mount_queue.qHead        = NULL;
  1016.     g_mount_queue.qTail        = NULL;
  1017.     g_mount_queue.qFlags    = NULL;
  1018.     g_ramdisk                = NULL;
  1019.     g_L2CR_pref                = false;
  1020.     g_L2CR_set                = false;
  1021.     g_L2CR_value            = 0;
  1022.     g_L2CR_available        = false;
  1023.     g_entry_ticks            = TickCount();
  1024.     
  1025.     g_vm_present = false;
  1026.     if (Gestalt(gestaltVMAttr, &response) == noErr)
  1027.         if (response & (1 << gestaltVMPresent))
  1028.             g_vm_present = true;
  1029.     if (Gestalt(gestaltNativeCPUfamily, &response) == noErr)
  1030.     {
  1031.         if (response == gestaltCPU750)
  1032.             g_L2CR_available = true;
  1033.     } else if (Gestalt(gestaltNativeCPUtype, &response) == noErr)
  1034.         if (response == gestaltCPU750)
  1035.             g_L2CR_available = true;
  1036.  
  1037. //    g_L2CR_available = true;
  1038.     
  1039.     g_arch_PCI = false;
  1040.     if (Gestalt(gestaltOpenFirmwareInfo, &response) == noErr)
  1041.         if (Gestalt(gestaltNameRegistryVersion, &response) == noErr)
  1042.             g_arch_PCI = true;
  1043.     if (((long)RegistryEntryIDInit == kUnresolvedCFragSymbolAddress)||
  1044.         ((long)FlushProcessorCache == kUnresolvedCFragSymbolAddress))
  1045.             g_arch_PCI = false;
  1046.  
  1047.     g_page_size = g_arch_PCI ? GetLogicalPageSize() : 4096;
  1048.  
  1049.     GetWMgrPort(&oldPort);
  1050.     SetPort(oldPort);
  1051.  
  1052.     // Setup default BootX options
  1053.     GetIndString(g_kernel_args, string_kernel_args, 1);
  1054.     GetIndString(tempStr, string_boot_delay, 1);
  1055.     StringToNum(tempStr, (long *)&g_autoboot_delay);
  1056. //    if (g_autoboot_delay > 30)
  1057. //        g_autoboot_delay = 30;
  1058.     g_autoboot_delay    *= 60;
  1059.     g_current_choice    = boot_macos;
  1060.     g_video_of_only        = false;
  1061.         
  1062.     // Setup device tree options
  1063.     device_tree_skip_macos            = 1;        // Skip MacOS drivers
  1064.     device_tree_max_prop_length        = 1024;        // Max copied property length
  1065.  
  1066.     // Locate the kernel and ramdisk files
  1067.     lookup_kernels();
  1068.     g_boot_choices[boot_linux][1] = (g_kernel_items_count != 0);
  1069.     if (g_kernel_items_count)
  1070.         locate_ramdisk();
  1071.     g_use_ramdisk = g_have_ramdisk;
  1072.     
  1073. #if BOOTX_BUILD_INIT
  1074.     // Locate MkLinux booter
  1075.     g_boot_choices[boot_mklinux][1] = locate_mklinux();
  1076. #endif    
  1077.     
  1078. #if BOOTX_TRACE
  1079.     ST_Printf(0,0,"VM present                 : %d¥n", g_vm_present);
  1080.     ST_Printf(0,0,"Page size                  : %d¥n", g_page_size);
  1081.     ST_Printf(0,0,"Autoboot_delay             : %d¥n", g_autoboot_delay);
  1082.     ST_Printf(0,0,"L2CR available on this CPU : %d¥n", g_L2CR_available);
  1083.     if (g_have_ramdisk)
  1084.         ST_Printf(0,0,"RAM-disk found¥n");
  1085.     if (g_boot_choices[boot_linux][1])
  1086.         ST_Printf(0,0,"Linux kernel found¥n");
  1087.     if (g_boot_choices[boot_mklinux][1])
  1088.         ST_Printf(0,0,"MkLinux booter found¥n");
  1089. #endif
  1090.  
  1091.  
  1092.     if (!g_boot_choices[boot_linux][1] && !g_boot_choices[boot_mklinux][1])
  1093.     {
  1094.         DEBUG_ERR(0, error_no_kernel);
  1095.         goto bail;
  1096.     }
  1097.         
  1098.     // Create main dialog box
  1099.     if (!create_dialog())
  1100.         goto bail;
  1101.  
  1102.     if (g_kernel_items_count)
  1103.         build_kernels_menu();
  1104.         
  1105.     // Load eventual prefs file
  1106.     load_prefs();
  1107.  
  1108.     // Display the dialog
  1109.     SelectDialogItemText(g_dialog, field_kernel_args, 0, 255);
  1110.     ShowWindow(g_dialog);
  1111.     DrawDialog(g_dialog);
  1112.  
  1113.  
  1114.     // Main event loop
  1115.  
  1116.     finished = false;
  1117.     simulate = false;
  1118.     stop_counter = false;
  1119. #if BOOTX_BUILD_INIT
  1120.     counter_on = true;
  1121. #else
  1122.     counter_on = false;
  1123. #endif
  1124.     
  1125.     last_disp_ticks = g_entry_ticks - 60;
  1126.  
  1127.     if (GetStdFilterProc(&std_filter) != noErr)
  1128.     {
  1129.         std_filter = NULL;
  1130.         DEBUG_ERR(0,error_no_std_filter);
  1131.     }
  1132.     
  1133.     while(!finished)
  1134.     {
  1135.         EventRecord    event;
  1136.         short        itemHit;
  1137.         DialogPtr    dialog;
  1138.         Boolean        handled;
  1139.         Boolean        hasEvent;
  1140.         
  1141.         SetPort(g_dialog);
  1142.         hasEvent = WaitNextEvent(everyEvent, &event, 1, NULL);
  1143.         SetPort(g_dialog);
  1144.         SetZone(g_my_zone);
  1145.     
  1146.         itemHit = 0;
  1147.         dialog = g_dialog;
  1148.         handled = false;
  1149.         
  1150.         if (counter_on)
  1151.         {
  1152.             UInt32    now = TickCount();
  1153.             
  1154.             if ((now - g_entry_ticks) >= g_autoboot_delay)
  1155.             {
  1156.                 counter_on = false;
  1157.                 itemHit = g_boot_choices[g_current_choice][0];
  1158.                 simulate = true;
  1159.                 handled = true;
  1160.             }
  1161.             else if ((now - last_disp_ticks) >= 30)
  1162.             {
  1163.                 static char temp[256];
  1164.                 
  1165.                 sprintf(temp, "Boot in %d seconds   ", (int)((g_autoboot_delay - (now - g_entry_ticks)) / 60));
  1166.                 c2pstr(temp);
  1167.                 SetDialogItemText(g_status_item, (StringPtr)temp);
  1168.                 last_disp_ticks = now;
  1169.             }
  1170.         }
  1171.         
  1172.         if (!handled)
  1173.             handled = ((std_filter != NULL)
  1174.                 ? CallModalFilterProc(std_filter, g_dialog, &event, &itemHit)
  1175.                 : false);
  1176.  
  1177.         if (!handled && hasEvent)
  1178.         {
  1179.             UInt8 c;
  1180.             
  1181.             switch(event.what)
  1182.             {
  1183.                 case updateEvt:
  1184.                     if ((DialogPtr)event.message == g_dialog)
  1185.                     {
  1186.                         handled = TRUE;
  1187.                         BeginUpdate(g_dialog);
  1188.                         RGBBackColor(&g_back_color);
  1189.                         DrawDialog(g_dialog);
  1190.                         setup_default_buttons();
  1191.                         EndUpdate(g_dialog);
  1192.                     } else
  1193.                     {
  1194.                         BeginUpdate((WindowPtr)event.message);
  1195.                         EndUpdate((WindowPtr)event.message);
  1196.                     }
  1197.                     break;
  1198.                 
  1199.                 case keyDown:
  1200.                 case autoKey:
  1201.                     c = (event.message & charCodeMask);
  1202.             
  1203.                     if (event.modifiers & cmdKey)
  1204.                     {
  1205.                         switch(c)
  1206.                         {
  1207.                             case 'q':
  1208.                             case 'Q':
  1209.                                 itemHit = button_boot_macos;
  1210.                                 handled = true;
  1211.                                 break;
  1212.                             case 's':
  1213.                             case 'S':
  1214.                                 itemHit = button_set_default;
  1215.                                 handled = true;
  1216.                                 simulate = true;
  1217.                                 break;
  1218.                         }
  1219.                     } else
  1220.                     {
  1221.                         switch(c)
  1222.                         {
  1223.                             case 0x09:    // Tab
  1224.                                 do
  1225.                                     g_current_choice = (g_current_choice + 1) % boot_choice_count;
  1226.                                 while(!g_boot_choices[g_current_choice][1]);
  1227.                                 setup_default_buttons();
  1228.                                 handled = true;
  1229.                                 break;
  1230.                             /* This is done for us by the standard filter
  1231.                             case 0x0D:    // Return
  1232.                             case 0x03:    // Enter
  1233.                                 simulate = true;
  1234.                                 handled = true;
  1235.                                 itemHit = g_boot_choices[g_current_choice][0];
  1236.                                 break;
  1237.                             case 0x1B:
  1238.                                 simulate = true;
  1239.                                 handled = true;
  1240.                                 itemHit = button_boot_macos;
  1241.                                 break;
  1242.                             */
  1243.                         }
  1244.                     }
  1245.                     
  1246.                     // We stop the counter when a key is pressed    
  1247.                     stop_counter = true;        
  1248.                     break;
  1249.                 
  1250.                 case diskEvt:
  1251. #if BOOTX_BUILD_INIT
  1252.                     save_mount_event(&event);
  1253. #else                    
  1254.                     if ((HiWord(event.message) != noErr)&&(HiWord(event.message) != volOnLinErr))
  1255.                     {
  1256.                         Point pt = {100, 100};
  1257.                         DIBadMount(pt, event.message);
  1258.                     }
  1259. #endif
  1260.                     break;
  1261.             }
  1262.         }
  1263.         
  1264.         // All non-filtered events are given to the default event proc.
  1265.         if (!handled && IsDialogEvent(&event))
  1266.             handled = DialogSelect(&event, &dialog, &itemHit);
  1267.         
  1268.         if (handled)
  1269.         {
  1270.             if (dialog == g_dialog)
  1271.             {
  1272.                 int i;
  1273.                 
  1274.                 if (simulate)
  1275.                 {
  1276.                     Rect    itemBox;
  1277.                     short    itemType;
  1278.                     Handle    itemHandle;
  1279.                     UInt32    toto;
  1280.                     
  1281.                     GetDialogItem (g_dialog, itemHit, &itemType, &itemHandle, &itemBox);
  1282.                     HiliteControl((ControlHandle)itemHandle, 1);
  1283.                     Delay(10, &toto);
  1284.                     HiliteControl((ControlHandle)itemHandle, 0);
  1285.                     simulate = false;
  1286.                 }
  1287.                 for(i=0; i<boot_choice_count; i++)
  1288.                     if (g_boot_choices[i][0] == itemHit)
  1289.                     {
  1290.                         g_current_choice = i;
  1291.                         finished = true;
  1292.                         break;
  1293.                     }
  1294.                 switch(itemHit)
  1295.                 {
  1296.                     case button_set_default:
  1297.                         stop_counter = true;
  1298.                         save_prefs();
  1299.                         break;
  1300.                     case check_use_ram_disk:
  1301.                         stop_counter = true;
  1302.                         if (g_have_ramdisk)
  1303.                         {
  1304.                             g_use_ramdisk = !g_use_ramdisk;
  1305.                             SetControlValue(g_use_ramdisk_cntl, g_use_ramdisk);
  1306.                         }
  1307.                         break;
  1308.                     case check_video_of_only:
  1309.                         stop_counter = true;
  1310.                         g_video_of_only = !g_video_of_only;
  1311.                         SetControlValue(g_video_of_only_cntl, g_video_of_only);
  1312.                         break;
  1313.                     case check_set_l2cr:
  1314.                         stop_counter = true;
  1315.                         if (g_L2CR_available && g_L2CR_pref)
  1316.                         {
  1317.                             g_L2CR_set = !g_L2CR_set;
  1318.                             SetControlValue(g_set_L2CR_cntl, g_L2CR_set);
  1319.                         }
  1320.                         break;
  1321.                     case menu_kernels:
  1322.                         stop_counter = true;
  1323.                         break;                        
  1324.                     default:
  1325.                         break;
  1326.                 }
  1327.             }
  1328.         }
  1329.         if (counter_on && stop_counter)
  1330.         {
  1331.             counter_on = FALSE;
  1332.             SetDialogItemText(g_status_item, "¥p");
  1333.         }
  1334.     }
  1335.     
  1336.     switch (g_current_choice)
  1337.     {
  1338.         case boot_linux:
  1339.             get_options_from_dialog();
  1340.             dispose_dialog();
  1341. #if !BOOTX_BUILD_INIT
  1342.             SetZone(SystemZone());
  1343. #endif            
  1344.             prepare_and_boot(&g_kernel_items[g_kernel_items_choice]);
  1345.             SetZone(g_my_zone);
  1346.             break;
  1347.         case boot_mklinux:
  1348.             SetZone(g_my_zone);
  1349.             dispose_dialog();
  1350.             do_boot_mklinux();
  1351.             break;
  1352.     }
  1353.     
  1354. bail:
  1355.     
  1356.     SetZone(g_my_zone);
  1357.  
  1358.     if (g_dialog)
  1359.         dispose_dialog();
  1360.  
  1361.     GetWMgrPort(&oldPort);
  1362.     SetPort(oldPort);
  1363.  
  1364. #if BOOTX_BUILD_INIT
  1365.     SetZone(SystemZone());
  1366.     resend_mount_events();
  1367.     SetZone(g_my_zone);
  1368. #endif    
  1369.  
  1370. #if BOOTX_TRACE
  1371.     ST_TraceDispose();
  1372. #endif
  1373.  
  1374. #if BOOTX_BUILD_INIT
  1375.     FragmentTerminate();
  1376. #endif
  1377. }
  1378.  
  1379. void
  1380. check_burgundy_patch(void)
  1381. {
  1382.     THz                    oldZone;
  1383.     Handle                patchRsrc;
  1384.         
  1385.     oldZone = GetZone();
  1386.     SetZone(SystemZone());
  1387.     
  1388.     patchRsrc = Get1Resource('GLUE', 130);
  1389.     if (patchRsrc == NULL) {
  1390.         goto bail;
  1391.     }
  1392.     DetachResource(patchRsrc);
  1393.     HLock(patchRsrc);
  1394.     
  1395.     if (!CallUniversalProc((RoutineDescriptor *)*patchRsrc,
  1396.         kCStackBased | RESULT_SIZE(SIZE_CODE(sizeof(Boolean))))) {
  1397.         HUnlock(patchRsrc);
  1398.         DisposeHandle(patchRsrc);
  1399.     }    
  1400.  
  1401. bail:
  1402.     SetZone(oldZone);
  1403. }
  1404.  
  1405.  
  1406. /* The main boot operations are here: making of the boot-infos, loading of the
  1407.  * kernel, etc...
  1408.  *
  1409.  * !!! This function should really be broken in pieces for readability and
  1410.  *     maintainability !!!
  1411.  */
  1412. void
  1413. prepare_and_boot(kernel_item_t* kern_infos)
  1414. {
  1415.     PPCRegisterList    regList;    
  1416.     Handle            boot_resource;
  1417.     Handle            boot_resource_PPC;
  1418.     Ptr                devTree;
  1419.     UInt32            kern_size;
  1420.     UInt32            devTreeSize;
  1421.     UInt32            dispRegOff;
  1422.     UInt32            allocSpace;
  1423.     void*            strap_entry;
  1424.     UInt32            strap_phys_entry, strap_dest;
  1425.     UInt32*            map;
  1426.     UInt32*            map_loc;
  1427.     UInt32            map_size, boot_map_addr, strap_size, prec, i, j, k, temp_page;
  1428.     UInt32            setupVideo = false;
  1429.     void*            boot_glue_68k;
  1430.     void*            boot_glue_PPC;
  1431.     OSErr            err;
  1432.  
  1433. #if BOOTX_BUILD_INIT
  1434.     Ptr                saveBufPtr = LMGetBufPtr();
  1435. #endif
  1436.  
  1437.     g_stuff = (UInt8 *)g_stuff_ptr = NULL;
  1438.  
  1439. #if !BOOTX_BUILD_INIT
  1440.     SetCursor(*GetCursor(watchCursor));
  1441. #endif    
  1442.  
  1443.     if (g_arch_PCI) {
  1444.         err = build_pci_device_tree(&devTree, &devTreeSize, &dispRegOff);
  1445.         if (err != noErr)
  1446.             return;
  1447.     } else
  1448.     {
  1449.         devTree        = NULL;
  1450.         devTreeSize    = 0;
  1451.         dispRegOff    = 0;
  1452.     }
  1453.     if (check_kernel(kern_infos, true))
  1454.         goto out_freedevtree;
  1455.     if (g_use_ramdisk && (open_ramdisk(&g_ramdisk_spec) != noErr))
  1456.         goto out_close_kernel;
  1457.  
  1458.     /* First we calculate the sizes and offsets of the different
  1459.        elements to store with the kernel */
  1460.     if (!g_use_ramdisk)
  1461.         g_ramdisk_size = 0;
  1462.     kern_size = (kern_infos->file_size > kern_infos->mem_size) ?
  1463.         kern_infos->file_size : kern_infos->mem_size;
  1464.     g_stuff_offsets[offset_kernel]        = 0;
  1465.     g_stuff_offsets[offset_stack]        = prec = PAGE_ALIGN(kern_size);
  1466.     g_stuff_offsets[offset_bootinfo]    = prec = PAGE_ALIGN(prec + BOOT_KERNEL_STACK_SIZE);
  1467.     g_stuff_offsets[offset_arguments]    = prec = LINE_ALIGN(prec + sizeof(boot_infos_t));
  1468.     g_stuff_offsets[offset_color_map]    = prec = LINE_ALIGN(prec + g_kernel_args[0] + 1);
  1469.     g_stuff_offsets[offset_device_tree]    = prec = LINE_ALIGN(prec + BOOTX_COLORTABLE_SIZE);
  1470.     g_stuff_offsets[offset_ramdisk]        = prec = PAGE_ALIGN(prec + devTreeSize);
  1471.     g_stuff_offsets[offset_unmangler]    = prec = PAGE_ALIGN(prec + g_ramdisk_size);
  1472.     allocSpace = prec + g_page_size;
  1473.     
  1474. #if !BOOTX_BUILD_INIT
  1475.     SetZone(SystemZone());
  1476. #endif            
  1477.     
  1478. #if BOOTX_LOG_MAP
  1479.     open_log_file();
  1480.     log_printf("Original offsets:¥n");
  1481.     log_printf("g_stuff_offsets[offset_kernel]         = 0x%08lx¥n", g_stuff_offsets[offset_kernel]);
  1482.     log_printf("g_stuff_offsets[offset_stack]          = 0x%08lx¥n", g_stuff_offsets[offset_stack]);
  1483.     log_printf("g_stuff_offsets[offset_bootinfo]       = 0x%08lx¥n", g_stuff_offsets[offset_bootinfo]);
  1484.     log_printf("g_stuff_offsets[offset_arguments]      = 0x%08lx¥n", g_stuff_offsets[offset_arguments]);
  1485.     log_printf("g_stuff_offsets[offset_color_map]      = 0x%08lx¥n", g_stuff_offsets[offset_color_map]);
  1486.     log_printf("g_stuff_offsets[offset_device_tree]    = 0x%08lx¥n", g_stuff_offsets[offset_device_tree]);
  1487.     log_printf("g_stuff_offsets[offset_ramdisk]        = 0x%08lx¥n", g_stuff_offsets[offset_ramdisk]);
  1488.     log_printf("g_stuff_offsets[offset_unmangler]      = 0x%08lx¥n", g_stuff_offsets[offset_unmangler]);
  1489. #endif
  1490.  
  1491.     /* Allocate the big "stuffs" region where we store all those datas */
  1492. #if BOOTX_BUILD_INIT
  1493.     g_stuff    = (UInt8*)alloc_high_mem(allocSpace);
  1494.     err = memFullErr;
  1495. #else
  1496.     g_stuff    = (UInt8*)NewPtrSysClear(allocSpace);
  1497.     err = MemError();
  1498. #endif    
  1499.     if (!g_stuff) {
  1500.         DEBUG_ERR(err, error_alloc_stuffs);
  1501.         goto out_setzone;
  1502.     }
  1503.     err = noErr;
  1504.     g_stuff_ptr = (Ptr)g_stuff;
  1505.     g_stuff = (UInt8 *)PAGE_ALIGN(g_stuff);
  1506.     memset(g_stuff + g_stuff_offsets[offset_stack], 0, BOOT_KERNEL_STACK_SIZE);
  1507.  
  1508.     // -- Load kernel --
  1509.     if (load_kernel(kern_infos, g_stuff + g_stuff_offsets[offset_kernel]))
  1510.         goto out_setzone;
  1511. // --- Flush useless now
  1512. //    if (g_arch_PCI)
  1513. //        FlushProcessorCache(NULL, g_stuff + g_stuff_offsets[offset_kernel], g_kernel_memsize);
  1514. //    else
  1515. //        MakeDataExecutable(g_stuff + g_stuff_offsets[offset_kernel], g_kernel_memsize);
  1516.  
  1517.     // -- Fill boot infos --
  1518.     
  1519.     // Store version informations
  1520.     g_boot_infos = (boot_infos_t *)(g_stuff + g_stuff_offsets[offset_bootinfo]);
  1521.     memset(g_boot_infos, 0, sizeof(boot_infos_t));
  1522.     g_boot_infos->version                    = BOOT_INFO_VERSION;
  1523.     g_boot_infos->compatible_version        = BOOT_INFO_COMPATIBLE_VERSION;
  1524.     
  1525.     // Fill some fields of the boot_infos
  1526.     err = Gestalt(gestaltMachineType, (long *)&g_boot_infos->machineID);
  1527.     if (err != noErr)
  1528.         g_boot_infos->machineID = 0;
  1529.     g_boot_infos->architecture = 0;
  1530.  
  1531.     // Setup arch flags and memory map for NuBus 
  1532.     if (g_arch_PCI) {
  1533.         g_boot_infos->architecture |= BOOT_ARCH_PCI;
  1534.         g_load_base = 0;
  1535.         g_boot_infos->physMemoryMapSize = 0;
  1536.     } else {
  1537.         build_memory_map();
  1538.         g_boot_infos->architecture |= BOOT_ARCH_NUBUS;
  1539.         g_load_base = 0x200000;
  1540.         switch(g_boot_infos->machineID) {
  1541.             case gestaltPowerMac6100_60:
  1542.             case gestaltPowerMac6100_66:
  1543.             case 101: /* gestaltPowerMac6100_80 */
  1544.             case gestaltPowerMac7100_66:
  1545.             case gestaltPowerMac7100_80:
  1546.             case 113: /* gestaltPowerMac7100_80_chipped */
  1547.             case gestaltPowerMac8100_80:
  1548.             case gestaltPowerMac8100_100:
  1549.             case gestaltPowerMac8100_110:
  1550.             case gestaltPowerMac8100_120:
  1551.             case gestaltAWS9150_80:
  1552.             case gestaltAWS9150_120:
  1553.                 g_boot_infos->architecture |= BOOT_ARCH_NUBUS_PDM;
  1554.                 break;
  1555.             case gestaltPowerMac5200:
  1556.             case gestaltPowerMac6200:
  1557.                 g_boot_infos->architecture |= BOOT_ARCH_NUBUS_PERFORMA;
  1558.                 break;
  1559.             case gestaltPowerBook1400:
  1560.             case gestaltPowerBook5300:
  1561.             case gestaltPowerBookDuo2300:
  1562.                 g_boot_infos->architecture |= BOOT_ARCH_NUBUS_POWERBOOK;
  1563.                 break;
  1564.             /* No default case, we let the kernel boot unsupported machines,
  1565.                just in case... */
  1566.         }
  1567.     }
  1568.     
  1569. #if BOOTX_LOG_MAP
  1570.     log_printf("Arch flags: 0x%lx, machineID: %d¥n",
  1571.         g_boot_infos->architecture, g_boot_infos->machineID);
  1572.     if (g_boot_infos->architecture & BOOT_ARCH_NUBUS) {
  1573.         log_printf("phys memory map:¥n");
  1574.         for (i=0;i<g_boot_infos->physMemoryMapSize; i++)
  1575.             log_printf(" from 0x%08lx, 0x%08lx bytes¥n",
  1576.                 g_boot_infos->physMemoryMap[i].physAddr,
  1577.                 g_boot_infos->physMemoryMap[i].size);
  1578.     }
  1579. #endif
  1580.  
  1581.     // Total size of parameters after boot-infos
  1582.     g_boot_infos->totalParamsSize = BI_OFFSET(offset_unmangler);
  1583.  
  1584.     // Store the kernel params
  1585.     g_boot_infos->kernelParamsOffset        = BI_OFFSET(offset_arguments);
  1586.     g_kernel_args[g_kernel_args[0]+1]        = 0;
  1587.     memcpy(g_stuff + g_stuff_offsets[offset_arguments], &g_kernel_args[1], g_kernel_args[0]+1);
  1588.  
  1589.     // Make room for the colormap and store the offset. This offset will be used or cleared
  1590.     // when the display device infos are really gathered by the low-level booter
  1591.     g_boot_infos->dispDeviceColorsOffset    = BI_OFFSET(offset_color_map);
  1592.  
  1593.     // Copy in the device tree
  1594.     g_boot_infos->deviceTreeOffset            = BI_OFFSET(offset_device_tree);
  1595.     g_boot_infos->deviceTreeSize            = devTreeSize;
  1596.     g_boot_infos->dispDeviceRegEntryOffset    = dispRegOff;
  1597.     memcpy(g_stuff + g_stuff_offsets[offset_device_tree], devTree, devTreeSize);
  1598.  
  1599.     // -- Read in the ramdisk --
  1600.     if (g_use_ramdisk) {
  1601. #if BOOTX_LOG_MAP
  1602.         log_printf(0,0,"loading ramdisk...¥n");
  1603. #endif
  1604.         if (load_ramdisk(g_stuff + g_stuff_offsets[offset_ramdisk]))
  1605.             goto out_setzone;
  1606.         g_boot_infos->ramDisk                = BI_OFFSET(offset_ramdisk);
  1607.         g_boot_infos->ramDiskSize            = g_ramdisk_size;
  1608.     }
  1609.  
  1610.     // -- Build the copy-map that will be used by the boostrap to make --
  1611.     //      the kernel and all other allocated stuff contiguous
  1612.     
  1613.     // First make all the stuff resident (but not necessarily contiguous)
  1614.     err = make_resident(g_stuff, allocSpace, NO_BOOTSTRAP ? true : false);
  1615.     if (err != noErr)
  1616.         return;
  1617.  
  1618. #if !NO_BOOTSTRAP
  1619.  
  1620.     // Make a map of pages used by the kernel stuffs
  1621.     err = make_kernel_map(&map, &map_size);
  1622.     if (err != noErr) {
  1623.         DEBUG_ERR(err, error_map_kernel);
  1624.         return;
  1625.     }
  1626.  
  1627. #if BOOTX_LOG_MAP
  1628.     log_printf("kernel map built, %d entries, loading bootsrap...¥n", map_size);
  1629. #endif
  1630.  
  1631.     // the map size is multiplied by 2 to make room for "temp" copy
  1632.     // operations that will be generated when source pages overlap
  1633.     // destination. It's then multiplied by 12 which is the size of
  1634.     // an entry in the copy-table.
  1635.     strap_entry = load_bootstrap(map_size*24, &map_loc, &strap_size);
  1636.     if (!strap_entry) {
  1637.         DEBUG_ERR(err, error_load_bootstrap);
  1638.         return;
  1639.     }
  1640.  
  1641.     // Make the boostrap resident and contiguous
  1642.     err = make_resident(strap_entry, strap_size+g_page_size, true);
  1643.     if (err != noErr)
  1644.         return;
  1645.         
  1646.     // The boostrap will move itself just after the kernel.
  1647.     // We just make sure that source and dest don't overlap
  1648.     // itself or one of the kernel pages
  1649.     strap_size            = PAGE_ALIGN(strap_size);
  1650.     strap_dest            = g_load_base + g_stuff_offsets[offset_unmangler];
  1651.     strap_phys_entry    = (UInt32)get_physical(strap_entry);
  1652.     if ((strap_phys_entry < (strap_dest + strap_size)) &&
  1653.         (strap_phys_entry > strap_dest - strap_size))
  1654.         strap_dest = PAGE_ALIGN(strap_phys_entry + strap_size);
  1655.     do
  1656.     {
  1657.         int overlap = false;
  1658.         for (i=0; i<map_size; i++)
  1659.             if ((map[i] >= strap_dest)&&(map[i] < (strap_dest+strap_size))) {
  1660.                 overlap = true;
  1661.                 strap_dest += g_page_size;
  1662.                 break;
  1663.             }
  1664.         if (!overlap)
  1665.             break;
  1666.     } while(true);
  1667.     g_stuff_offsets[offset_unmangler] = strap_dest - g_load_base;
  1668.     boot_map_addr = strap_dest + ((UInt32)map_loc - (UInt32)strap_entry);
  1669.     temp_page = PAGE_ALIGN(strap_dest + strap_size);
  1670.     
  1671. #if BOOTX_LOG_MAP
  1672.     log_printf("strap entry      : 0x%lx¥n", strap_entry);
  1673.     log_printf("strap dest       : 0x%lx¥n", strap_dest);
  1674.     log_printf("strap phys entry : 0x%lx¥n", strap_phys_entry);
  1675.     log_printf("temp_page        : 0x%lx¥n", temp_page);
  1676.     log_printf("load_base        : 0x%lx¥n", g_load_base);
  1677. #endif
  1678.     
  1679.     // Now, we build the page-copy list for the bootstrap. For each
  1680.     // kernel page, we first check if the destination already holds
  1681.     // a kernel page. If this is the case, then this page is copied
  1682.     // to a temp buffer, the original copy is done, and the temp
  1683.     // buffer is set to the original source
  1684. #if BOOTX_LOG_MAP
  1685.     log_printf("Copy map:¥n");
  1686. #endif
  1687.  
  1688.     k = 0;
  1689.     for(i=0; i<map_size; i++)
  1690.     {
  1691.         UInt32    src_page    = map[i];
  1692.         UInt32    dst_page    = g_load_base + g_stuff_offsets[offset_kernel] + (g_page_size * i);
  1693.         
  1694.         if (src_page == dst_page)
  1695.             continue;
  1696.             
  1697.         /* Check if the destination overlaps a yet uncopied page */
  1698.         for (j=i+1; j<map_size; j++)
  1699.         {
  1700.             if (dst_page == map[j])
  1701.             {
  1702.                 /* It overlaps. We add a "temp" copy of the dest page */
  1703.                 map_loc[k++] = dst_page;
  1704.                 map_loc[k++] = map[j] = get_temp_page(&temp_page, map+i, map_size-i);
  1705.                 map_loc[k++] = g_page_size;
  1706. #if BOOTX_LOG_MAP
  1707.                 log_printf("T 0x%08lx -> 0x%08lx¥n", map_loc[k-3], map_loc[k-2]);
  1708. #endif
  1709.                 break;
  1710.             }
  1711.         }
  1712.         map_loc[k++] = src_page;
  1713.         map_loc[k++] = dst_page;
  1714.         map_loc[k++] = g_page_size;
  1715. #if BOOTX_LOG_MAP
  1716.         log_printf("  0x%08lx -> 0x%08lx¥n", map_loc[k-3], map_loc[k-2]);
  1717. #endif
  1718.     }
  1719.     map_loc[k++] = 0;
  1720.     map_loc[k++] = 0;
  1721.     map_loc[k++] = 0;
  1722.  
  1723. #if BOOTX_LOG_MAP
  1724.     log_printf("list of %d copies for %d pages, %ld bytes¥n",
  1725.         (k/3), map_size, g_stuff_offsets[offset_unmangler]);
  1726. #endif
  1727.  
  1728.     DisposePtr((Ptr)map);
  1729.  
  1730. #endif // !NO_BOOTSTRAP
  1731.     
  1732.     // -- Load the low-level 68k boot glue --
  1733.     
  1734. #if !BOOTX_BUILD_INIT
  1735.     SetZone(SystemZone());
  1736. #endif            
  1737.     boot_resource = Get1Resource('GLUE', code_boot_glue68k);
  1738.     if (!boot_resource)
  1739.     {
  1740.         err = ResError();
  1741.         DEBUG_ERR(err, error_load_bootstrap68k);
  1742.         goto out_setzone;
  1743.     }
  1744.     HNoPurge(boot_resource);
  1745.     DetachResource(boot_resource);
  1746.     HLock(boot_resource);
  1747.     boot_glue_68k    = *boot_resource;
  1748.     
  1749.     // -- Load the low-level PPC boot glue --
  1750.  
  1751.     boot_resource_PPC = Get1Resource('GLUE', code_boot_gluePPC);
  1752.     if (!boot_resource_PPC)
  1753.     {
  1754.         err = ResError();
  1755.         DEBUG_ERR(err, error_load_bootstrapPPC);
  1756.         goto out_setzone;
  1757.     }
  1758.     HNoPurge(boot_resource_PPC);
  1759.     DetachResource(boot_resource_PPC);
  1760.     HLock(boot_resource_PPC);
  1761.     boot_glue_PPC    = *boot_resource_PPC;
  1762.  
  1763.     // -- Setup PPC registers for supervisor mode --
  1764.  
  1765. #if NO_BOOTSTRAP
  1766.     regList.PC        = (UInt32)g_kernel_entry;
  1767.     regList.GPR[1]    = (UInt32)g_stuff + g_stuff_offsets[offset_stack] + BOOT_KERNEL_STACK_SIZE - 512;
  1768.     regList.GPR[2]    = 0;
  1769.     regList.GPR[3]    = 'BooX';
  1770.     regList.GPR[4]    = (UInt32)g_stuff + g_stuff_offsets[offset_bootinfo];
  1771.     regList.GPR[5]    = 0;
  1772. #else
  1773.     regList.PC        = (unsigned long)strap_entry;
  1774.     regList.GPR[1]    = g_load_base + g_stuff_offsets[offset_stack] + BOOT_KERNEL_STACK_SIZE - 512;    // The stack for the kernel entry
  1775.     regList.GPR[2]    = 1;                                                    // r2 flag must be set to 1 by BootX 
  1776.     regList.GPR[3]    = 'BooX';                                                // r3 contains 'BooX' ($426F6F58)
  1777.     regList.GPR[4]    = g_load_base + g_stuff_offsets[offset_bootinfo];        // r4 contains the boot infos ptr
  1778.     regList.GPR[5]    = NULL; /*iMacHack;*/                                    // r5 NULL, replaced by low-bootsrap with map base of fb
  1779.     regList.GPR[6]    = strap_phys_entry;                                        // r6 contains phys addr. of bootstrap
  1780.     regList.GPR[7]    = strap_dest;                                            // r7 contains dest addr. of bootstrap
  1781.     regList.GPR[8]    = strap_size;
  1782.     regList.GPR[9]    = boot_map_addr;
  1783.     regList.GPR[10]    = kern_infos->entry - (UInt32)g_stuff + g_load_base + g_stuff_offsets[offset_kernel];
  1784.     regList.GPR[11]    = 0;
  1785. #endif
  1786.  
  1787. #if BOOTX_LOG_MAP
  1788.     log_printf("registers on entry:¥n");
  1789.     log_printf("-------------------¥n");
  1790.     log_printf(" PC:  0x%lx (logical)¥n", regList.PC);
  1791.     log_printf(" r1:  0x%lx (SP)¥n", regList.GPR[1]);
  1792.     log_printf(" r2:  0x%lx (should be 1)¥n", regList.GPR[2]);
  1793.     log_printf(" r3:  0x%lx (BooX)¥n", regList.GPR[3]);
  1794.     log_printf(" r4:  0x%lx (boot_infos)¥n", regList.GPR[4]);
  1795.     log_printf(" r5:  0x%lx (fb map address)¥n", regList.GPR[5]);
  1796.     log_printf(" r6:  0x%lx (strap_phys)¥n", regList.GPR[6]);
  1797.     log_printf(" r7:  0x%lx (strap_dest)¥n", regList.GPR[7]);
  1798.     log_printf(" r8:  0x%lx (strap_size)¥n", regList.GPR[8]);
  1799.     log_printf(" r9:  0x%lx (boot_map_phys)¥n", regList.GPR[9]);
  1800.     log_printf(" r10: 0x%lx (kernel entry)¥n", regList.GPR[10]);
  1801.     log_printf(" r11: 0x%lx (do BAT mapping)¥n", regList.GPR[11]);
  1802. #endif
  1803.  
  1804.     // -- Call the low-level PPC boot glue (returns a pointer to an UPP) --
  1805.     //    this call will make sure the code fragment is prepared and returns a pointer
  1806.     //    that can later be called by the 68k code
  1807.     boot_glue_PPC = (void *)CallUniversalProc(boot_glue_PPC, kCStackBased | RESULT_SIZE(SIZE_CODE(sizeof(void*))));
  1808.  
  1809.     // -- Call the low-level 68k boot glue (installs the shutdown proc) --
  1810. #if BOOTX_BUILD_INIT
  1811.     setupVideo = g_video_of_only;
  1812. #endif    
  1813.     CallUniversalProc(boot_glue_68k, uppLowLevelBoot68kProcInfo, ®List, g_boot_infos, boot_glue_PPC, setupVideo);
  1814.     
  1815.     // -- Reboot --
  1816.  
  1817.     check_burgundy_patch();
  1818.  
  1819. #if BOOTX_LOG_MAP
  1820.     log_printf("Sending MacOS shutdown...¥n");
  1821.     close_log_file();
  1822. #endif
  1823. #if BOOTX_BUILD_INIT
  1824.     ShutDwnStart();
  1825.     DebugStr("¥pShould not get here !");
  1826. #else
  1827.     send_restart_to_finder();
  1828. #endif
  1829.     
  1830.     return;
  1831.  
  1832.  out_disphandle:
  1833.      DisposeHandle(boot_resource);
  1834.  out_setzone:
  1835. #if BOOTX_LOG_MAP
  1836.     close_log_file();
  1837. #endif
  1838.     if (g_stuff_ptr)
  1839.         DisposePtr((Ptr)g_stuff_ptr);
  1840.     SetZone(g_my_zone);
  1841.     if (g_use_ramdisk)
  1842.         FSClose(g_ramdisk_ref);
  1843.  out_close_kernel:
  1844.      if (kern_infos->file_ref) {
  1845.         FSClose(kern_infos->file_ref);
  1846.         kern_infos->file_ref = 0;
  1847.     }
  1848.  out_freedevtree:
  1849. #if BOOTX_BUILD_INIT
  1850.     LMSetBufPtr(saveBufPtr);
  1851. #else
  1852.     DisposePtr(devTree);
  1853. #endif
  1854.  
  1855.  
  1856. }
  1857.  
  1858. static void
  1859. add_l2cr_property(UInt32 l2cr_value)
  1860. {
  1861.     RegEntryIter            iterator;
  1862.     RegEntryIterationOp        operation;
  1863.     OSStatus                err;
  1864.     Boolean                    done, found;
  1865.     char                    buffer[1024];
  1866.     RegEntryID                root_node_id;
  1867.     RegEntryID                entryID;
  1868.     Boolean                    first;
  1869.     
  1870.     // Create an Iterator
  1871.     operation = kRegIterContinue;    
  1872.     err = RegistryEntryIterateCreate(&iterator);
  1873.     if (err != noErr)
  1874.         return;
  1875.     
  1876.     err = RegistryEntryIDInit(&root_node_id);
  1877.     if (err != noErr) {
  1878.         RegistryEntryIterateDispose(&iterator);
  1879.         return;
  1880.     }
  1881.  
  1882.     err = RegistryCStrEntryLookup(NULL, "Devices:device-tree", &root_node_id);
  1883.     if (err != noErr) {
  1884.         RegistryEntryIDDispose(&root_node_id);
  1885.         RegistryEntryIterateDispose(&iterator);
  1886.         return;
  1887.     }
  1888.  
  1889.     RegistryEntryIterateSet(&iterator, &root_node_id);
  1890.     first = true;
  1891.     found = false;
  1892.     
  1893.     do {
  1894.         RegPropertyValueSize size;
  1895.             
  1896.         err = RegistryEntryIterate(&iterator, first ? kRegIterChildren : kRegIterContinue, &entryID, &done);
  1897.         first = false;
  1898.         if (!done && (err == noErr)) {
  1899.             size = 1024;
  1900.             err = RegistryPropertyGet(&entryID, "device_type", buffer, &size);
  1901.             if (err == noErr) {
  1902.                 if ((strcmp(buffer, "cpus") == 0) || (strcmp(buffer, "cpu") == 0)) {
  1903.                     found = true;
  1904.                     RegistryPropertyCreate(&entryID, "l2cr-value", &l2cr_value, 4);
  1905.                     break;
  1906.                 }
  1907.             }
  1908.         }
  1909.     } while (!done && !found && (err == noErr));
  1910.  
  1911.     RegistryEntryIterateDispose(&iterator);
  1912.     RegistryEntryIDDispose(&root_node_id);
  1913. }
  1914.  
  1915. OSErr
  1916. build_pci_device_tree(Ptr* outDevTree, UInt32 *outDevTreeSize, UInt32 *outDispRegOff)
  1917. {
  1918.     Ptr                devTree;
  1919.     OSErr            err;
  1920.     
  1921.     // First make a copy of the device tree.
  1922. #if BOOTX_BUILD_INIT
  1923.     Ptr    saveBufPtr = LMGetBufPtr();
  1924.     devTree    = alloc_high_mem(NAME_REGISTRY_MAX_SIZE);
  1925.     err = memFullErr;
  1926. #else
  1927.     devTree    = NewPtrSysClear(NAME_REGISTRY_MAX_SIZE);
  1928.     err = MemError();
  1929. #endif    
  1930.     if (devTree == NULL) {
  1931.         if (err == noErr) err = memFullErr;
  1932.         DEBUG_ERR(err, error_alloc_device_tree);
  1933.         return err;
  1934.     }
  1935.     err = noErr;
  1936.     
  1937.     /* Add the "l2cr-value" property to the device-tree:cpu(s) node */
  1938.     if (g_L2CR_available && g_L2CR_pref && g_L2CR_set)
  1939.         add_l2cr_property(g_L2CR_value);
  1940.     
  1941.     *outDevTreeSize = NAME_REGISTRY_MAX_SIZE;
  1942.     err = copy_device_tree(devTree, outDevTreeSize, outDispRegOff);
  1943.     if (err != noErr && (*outDevTreeSize > NAME_REGISTRY_MAX_SIZE)) {
  1944.         DEBUG_ERR(memFullErr, error_device_tree_ovflw);
  1945. #if BOOTX_BUILD_INIT
  1946.         LMSetBufPtr(saveBufPtr);
  1947. #else
  1948.         DisposePtr(devTree);        
  1949. #endif
  1950.         return err;
  1951.     } else if (err != noErr) {
  1952.         DEBUG_ERR(err, error_copy_device_tree);
  1953. #if BOOTX_BUILD_INIT
  1954.         LMSetBufPtr(saveBufPtr);
  1955. #else
  1956.         DisposePtr(devTree);        
  1957. #endif
  1958.     }
  1959.     
  1960.     *outDevTree = devTree;
  1961.     
  1962.     return noErr;    
  1963. }
  1964.  
  1965. void
  1966. build_memory_map(void)
  1967. {    
  1968.     Ptr base = *((Ptr *)MACOS_MEMMAP_PTR_ADDR);
  1969.     int len = *((UInt16 *)MACOS_MEMMAP_SIZE_ADDR);
  1970.     int i;
  1971.     
  1972.     if (len <= MACOS_MEMMAP_BANK_0FFSET)
  1973.         return;
  1974.         
  1975.     base += MACOS_MEMMAP_BANK_0FFSET;
  1976.     len -= MACOS_MEMMAP_BANK_0FFSET;
  1977.     i = 0;
  1978.     
  1979.     while(len >= 8) {
  1980.         UInt32 addr = *((UInt32*)base);
  1981.         UInt32 size = *((UInt32*)(base+4));
  1982.         
  1983.         if (size) {
  1984.             if ((i>0) && ((g_boot_infos->physMemoryMap[i-1].physAddr +
  1985.                 g_boot_infos->physMemoryMap[i-1].size) == addr)) {
  1986.                 g_boot_infos->physMemoryMap[i-1].size += size;
  1987.             } else {    
  1988.                 g_boot_infos->physMemoryMap[i].physAddr = addr;
  1989.                 g_boot_infos->physMemoryMap[i].size = size;
  1990.                 i++;
  1991.             }
  1992.         }
  1993.         base += 8;
  1994.         len -= 8;
  1995.     }
  1996.     g_boot_infos->physMemoryMapSize = i;
  1997. }
  1998.  
  1999. UInt32
  2000. get_temp_page(UInt32 *cur_temp, UInt32 *used_map, UInt32 used_size)
  2001. {
  2002.     UInt32    page = *cur_temp;
  2003.     UInt32    i;
  2004.  
  2005. again:
  2006.     for (i=0; i<used_size; i++)
  2007.         if (used_map[i] == page)
  2008.         {
  2009.             page += g_page_size;
  2010.             goto again;
  2011.         }
  2012.         
  2013.     *cur_temp = page + g_page_size;
  2014.     
  2015.     return page;
  2016. }
  2017.  
  2018. /* This function will build a simple map of the physical pages used
  2019.    by the kernel stuffs
  2020.  */
  2021. OSErr
  2022. make_kernel_map(UInt32 **out_map, UInt32 *out_size)
  2023. {
  2024.     LogicalToPhysicalTable    table;
  2025.     unsigned long            count, i;
  2026.     OSErr                    err;
  2027.     UInt32                    page_count;
  2028.     UInt8*                    ptr;
  2029.     
  2030.     page_count    = g_stuff_offsets[offset_unmangler] / g_page_size;
  2031.     ptr            = g_stuff;
  2032.     
  2033.     *out_map = (UInt32 *)NewPtrClear(page_count * sizeof(UInt32));
  2034.     if (*out_map == NULL)
  2035.         return memFullErr;
  2036.     
  2037.     for (i=0; i<page_count; i++)
  2038.     {
  2039.         /* First get all physical/logical mappings */    
  2040.         table.logical.address    = g_stuff + i*g_page_size;
  2041.         table.logical.count        = 1024;
  2042.         count = sizeof( table ) / sizeof( MemoryBlock ) - 1;
  2043.         err = GetPhysical( &table, &count );
  2044.         if ( err != noErr)
  2045.             return err;
  2046.         (*out_map)[i] = (UInt32)table.physical[0].address;
  2047.     }
  2048.  
  2049.     *out_size = page_count;
  2050.     
  2051.     return noErr;
  2052. }
  2053.  
  2054. /* Make a portion of memory resident. */
  2055. OSErr
  2056. make_resident(void* ptr, unsigned long size, Boolean contiguous)
  2057. {
  2058.     OSErr    err;
  2059.     
  2060. /*
  2061.     if (!g_vm_present)
  2062.         return noErr;
  2063. */
  2064.         
  2065.     if (size % g_page_size)
  2066.         size = size + g_page_size - (size % g_page_size);
  2067.  
  2068.     err = contiguous ? LockMemoryContiguous(ptr, size) : LockMemory(ptr, size);
  2069.  
  2070. bail:
  2071.     if (err != noErr)
  2072.         DEBUG_ERR(err, error_lock_memory);
  2073.     return err;
  2074. }
  2075.  
  2076. /* Get the physical address, if possible, of a pointer. Note that
  2077.  * we fail silently since we _do_ fail sometimes, like for screen
  2078.  * base address. In this case, we just return the original pointer
  2079.  */
  2080. UInt8*
  2081. get_physical(void* ptr)
  2082. {
  2083.     LogicalToPhysicalTable    table;
  2084.     unsigned long            count;
  2085.     OSErr                    err;
  2086.     
  2087.     table.logical.address    = ptr;
  2088.     table.logical.count        = 1024;
  2089.     count = sizeof( table ) / sizeof( MemoryBlock ) - 1;
  2090.     
  2091.     err = GetPhysical( &table, &count );
  2092.     if ( err != noErr)
  2093.         return ptr;
  2094.     
  2095.     return (UInt8 *)(table.physical[0].address);
  2096. }
  2097.  
  2098. /* Open the kernel image and find out what sort of image it is.
  2099.  * For ELF kernels we find out the offset, size on disk and
  2100.  * size in memory of the kernel image.
  2101.  */
  2102. #define MAX_PHDRS    10
  2103.  
  2104. OSErr
  2105. check_kernel(kernel_item_t*    kern_infos, Boolean will_load)
  2106. {
  2107.     OSErr        err;
  2108.     long        nb;
  2109.     int         i;
  2110.     Elf32_Ehdr    e;
  2111.     Elf32_Phdr    p[MAX_PHDRS];
  2112.     UInt32        total_file_size;
  2113.     Boolean        wasFolder;
  2114.     Boolean        wasAlias;
  2115.             
  2116.     /* Resolve it in case it was an alias - should do it silently however !*/
  2117.     ResolveAliasFile(&kern_infos->file, true, &wasFolder, &wasAlias);
  2118.  
  2119.     err = FSpOpenDF(&kern_infos->file, fsRdPerm, &kern_infos->file_ref);
  2120.     if (err != noErr) {
  2121.         if (will_load)
  2122.             DEBUG_ERR(err, error_open_kernel);
  2123.         return err;
  2124.     }
  2125.     err = GetEOF(kern_infos->file_ref, &nb);
  2126.     if (err != noErr) {
  2127.         if (will_load)
  2128.             DEBUG_ERR(err, error_get_kernel_size);
  2129.         goto out;
  2130.     }
  2131.     total_file_size = nb;
  2132.     nb = sizeof(e);
  2133.     err = FSRead(kern_infos->file_ref, &nb, &e);
  2134.     if (err != noErr) {
  2135.         if (will_load)
  2136.             DEBUG_ERR(err, error_read_kernel_header);
  2137.         goto out;
  2138.     }
  2139.  
  2140.     /* Check if it is an executable elf binary. */
  2141.     err = -1;
  2142.     if (!(e.e_ident[EI_MAG0] == ELFMAG0 && e.e_ident[EI_MAG1] == ELFMAG1 &&
  2143.           e.e_ident[EI_MAG2] == ELFMAG2 && e.e_ident[EI_MAG3] == ELFMAG3)) {
  2144.         if (will_load)
  2145.             DEBUG_ERR(0, error_kernel_not_elf);
  2146.         goto out;
  2147.     }
  2148.     if (e.e_ident[EI_CLASS] != ELFCLASS32
  2149.         || e.e_ident[EI_DATA] != ELFDATA2MSB) {
  2150.         if (will_load)
  2151.             DEBUG_ERR(0, error_kernel_not_PPC32MSB);
  2152.         goto out;
  2153.     }
  2154.     
  2155.     if (!will_load) {
  2156.         FSClose(kern_infos->file_ref);
  2157.         kern_infos->file_ref = 0;
  2158.         return noErr;
  2159.     }
  2160.  
  2161.     /* Read in the program header */
  2162.     if (e.e_phnum > MAX_PHDRS)
  2163.         e.e_phnum = MAX_PHDRS;
  2164.     nb = e.e_phnum * sizeof(Elf32_Phdr);
  2165.     if ((err = SetFPos(kern_infos->file_ref, fsFromStart, (long) e.e_phoff)) != noErr
  2166.         || (err = FSRead(kern_infos->file_ref, &nb, (Ptr) p)) != noErr) {
  2167.         DEBUG_ERR(err, error_read_kernel_header2);
  2168.         goto out;
  2169.     }
  2170.     
  2171.     kern_infos->file_size    = 0;
  2172.     kern_infos->offset        = 0;
  2173.     kern_infos->mem_size    = 0;
  2174.     kern_infos->entry        = 0;
  2175.  
  2176. #define ADDRMASK    0x0fffffff
  2177.  
  2178.     /* Scan through the program header */
  2179.     for (i = 0; i < e.e_phnum; ++i) {
  2180.         unsigned int off = 0;
  2181.         if (p[i].p_type != PT_LOAD || p[i].p_offset == 0)
  2182.             continue;
  2183.         if (kern_infos->file_size == 0) {
  2184.             kern_infos->offset = p[i].p_offset;
  2185.             kern_infos->entry = ((e.e_entry & ADDRMASK) - (p[i].p_vaddr & ADDRMASK));
  2186.         } else if (p[i].p_offset > kern_infos->offset) {
  2187.             off = p[i].p_offset - kern_infos->offset;
  2188.         } else
  2189.             continue;
  2190.         kern_infos->file_size = p[i].p_filesz + off;
  2191.         kern_infos->mem_size = p[i].p_memsz + off;
  2192.     }
  2193.     err = -1;
  2194.     if (kern_infos->file_size == 0) {
  2195.         DEBUG_ERR(0, error_no_loadable_seg);
  2196.         goto out;
  2197.     }
  2198.     if (kern_infos->file_size + kern_infos->offset > total_file_size)
  2199.         kern_infos->file_size = total_file_size - kern_infos->offset;
  2200.  
  2201.     return 0;
  2202.  
  2203.  out:
  2204.  
  2205.      if (kern_infos->file_ref) {
  2206.         FSClose(kern_infos->file_ref);
  2207.         kern_infos->file_ref = 0;
  2208.     }
  2209.     return err;
  2210. }
  2211.  
  2212. void *
  2213. load_bootstrap(long mapSize, UInt32** outMapBegin,UInt32 *outTotalSize)
  2214. {
  2215.     THz                    oldZone;
  2216.     Handle                krsrc;
  2217.     OSErr                err;
  2218.     CFragConnectionID    fragID;
  2219.     Ptr                    fragEntry, loc;
  2220.     Str255                errStr;
  2221.     UInt32                origSize, extOrigSize, newSize;
  2222.     
  2223.     oldZone = GetZone();
  2224. #if !BOOTX_BUILD_INIT
  2225.     SetZone(SystemZone());
  2226. #endif            
  2227.     
  2228.     krsrc = GetResource('BSTP', 1000);
  2229.     if (!krsrc)
  2230.         goto error;
  2231.     DetachResource(krsrc);
  2232.     origSize = GetHandleSize(krsrc);
  2233.     extOrigSize  = origSize;
  2234.     extOrigSize += 0x00000FFFUL;
  2235.     extOrigSize &= 0xFFFFF000UL;
  2236.     mapSize  += 0x00000FFFUL;
  2237.     mapSize  &= 0xFFFFF000UL;
  2238.     /* we add a page size since we'll align things */
  2239.     newSize      = extOrigSize + mapSize + g_page_size;
  2240.     /* we add another page since we make resident a bit more datas */
  2241.     SetHandleSize(krsrc, newSize + g_page_size);
  2242.     if (GetHandleSize(krsrc) != (newSize + g_page_size)) {
  2243.         DisposeHandle(krsrc);
  2244.         goto error;
  2245.     }
  2246.     HLock(krsrc);
  2247.     
  2248.     loc = *krsrc;
  2249.     loc = (Ptr)PAGE_ALIGN(loc);
  2250.     if (loc != *krsrc) {
  2251. #if BOOTX_TRACE
  2252.         ST_Printf(0,0,"boostrap moved from 0x%lx to 0x%lx¥n",
  2253.             *krsrc, loc);
  2254. #endif            
  2255.         BlockMove(*krsrc, loc, origSize);
  2256.     }
  2257.     *outMapBegin = (UInt32*)(loc + extOrigSize);
  2258.     *outTotalSize = newSize;
  2259.     
  2260.     err = GetMemFragment(loc, origSize, "¥pbootstrap", kPrivateCFragCopy, &fragID, &fragEntry, errStr);
  2261.     if (err != noErr)
  2262.     {
  2263.         DEBUG_ERR(err, error_prepare_bootstrap);
  2264.         DisposeHandle(krsrc);
  2265.         goto error;
  2266.     }
  2267.     
  2268.     SetZone(oldZone);
  2269.  
  2270. #if BOOTX_TRACE
  2271.     ST_Printf(0,0,"boostrap entry: 0x%lx¥n", ((void **)fragEntry)[0]);
  2272. #endif            
  2273.  
  2274.     return ((void **)fragEntry)[0];
  2275.     
  2276. error:
  2277.     SetZone(oldZone);
  2278.     return NULL;
  2279. }
  2280.  
  2281. /* Load in the kernel image, and fix up the entry point.
  2282.  */
  2283. OSErr
  2284. load_kernel(kernel_item_t* kern_infos, UInt8* where)
  2285. {
  2286.     OSErr err;
  2287.     UInt32 entry;
  2288.     UInt32 start;
  2289.     long nb;
  2290.     
  2291.     nb = kern_infos->file_size;
  2292.     if ((err = SetFPos(kern_infos->file_ref, fsFromStart, kern_infos->offset)) != noErr
  2293.         || (err = FSRead(kern_infos->file_ref, &nb, (Ptr)where)) != noErr) {
  2294.         DEBUG_ERR(err, error_read_kernel);
  2295.         return err;
  2296.     }
  2297.  
  2298.     entry = (UInt32)where + kern_infos->entry;
  2299.     start = *(UInt32 *)entry;
  2300.     if ((start > kern_infos->file_size) || ((UInt32 *)entry)[2] != 0)
  2301.         start = entry;
  2302.     else
  2303.         start = start + (UInt32)where;
  2304.     kern_infos->entry = start;
  2305.         
  2306.     return noErr;
  2307. }
  2308.  
  2309. /* Open the ramdisk file and find out how big it is */
  2310. OSErr
  2311. open_ramdisk(FSSpec *ramdiskSpec)
  2312. {
  2313.     OSErr err;
  2314.  
  2315.     err = FSpOpenDF(ramdiskSpec, fsRdPerm, &g_ramdisk_ref);
  2316.     if (err != noErr)
  2317.     {
  2318.         DEBUG_ERR(err, error_open_ramdisk);
  2319.         return err;
  2320.     }
  2321.     err = GetEOF(g_ramdisk_ref, (long *)&g_ramdisk_size);
  2322.     if (err != noErr)
  2323.     {
  2324.         DEBUG_ERR(err, error_get_rd_size);
  2325.         FSClose(g_ramdisk_ref);
  2326.     }
  2327.     return err;
  2328. }
  2329.  
  2330. /* Load the ramdisk file */
  2331. OSErr
  2332. load_ramdisk(UInt8* where)
  2333. {
  2334.     OSErr    err;
  2335.     
  2336.     err = FSRead(g_ramdisk_ref, (long *)&g_ramdisk_size, where);
  2337.     if (err != noErr)
  2338.     {
  2339.         DEBUG_ERR(err, error_read_ramdisk);
  2340.     }
  2341.     
  2342.     return err;    
  2343. }
  2344.  
  2345.  
  2346. #if !BOOTX_BUILD_INIT
  2347.  
  2348. #define kFinderSig 'FNDR'
  2349. #define kSystemType 'MACS'
  2350.  
  2351. /* Send a restart event to the finder */
  2352. OSErr
  2353. send_restart_to_finder(void)
  2354. {
  2355.     OSErr                    err = noErr;
  2356.     ProcessSerialNumber        sn;
  2357.     AEDesc                    address;
  2358.     AppleEvent                theAE, reply;
  2359.     
  2360.     err = find_finder_process(&sn);
  2361.     
  2362.     if ( err == noErr )    err = AECreateDesc( typeProcessSerialNumber, &sn, sizeof( ProcessSerialNumber ), &address );
  2363.     if ( err == noErr ) err = AECreateAppleEvent( kFinderSig, 'rest', &address, kAutoGenerateReturnID, kAnyTransactionID, &theAE);
  2364.     if ( err == noErr ) err = AESend( &theAE, &reply, kAENoReply + kAECanInteract + kAECanSwitchLayer, kAENormalPriority, kAEDefaultTimeout, nil, nil );
  2365.  
  2366.     return err;
  2367. }
  2368.  
  2369. /* We look for the Finder in the list of processes */
  2370. OSErr
  2371. find_finder_process(ProcessSerialNumberPtr processSN)
  2372. {
  2373.     ProcessInfoRec tempInfo;
  2374.     FSSpec procSpec;
  2375.     Str31 processName;
  2376.     OSErr myErr = noErr;
  2377.  
  2378.     /* nul out the PSN so we're starting at the beginning of the list */
  2379.     processSN->lowLongOfPSN = kNoProcess;
  2380.     processSN->highLongOfPSN = kNoProcess;
  2381.  
  2382.     /* initialize the process information record */
  2383.     tempInfo.processInfoLength = sizeof(ProcessInfoRec);
  2384.     tempInfo.processName = (unsigned char *)&processName;
  2385.     tempInfo.processAppSpec = &procSpec;
  2386.     /* loop through all the processes until we */
  2387.     /* 1) find the process we want */
  2388.     /* 2) error out because of some reason (usually, no more processes */
  2389.     do {
  2390.         myErr = GetNextProcess(processSN);
  2391.         if (myErr == noErr)
  2392.             GetProcessInformation(processSN, &tempInfo);
  2393.         
  2394.         if ( tempInfo.processSignature == 'MACS' && tempInfo.processType == 'FNDR' )
  2395.             break;
  2396.         
  2397.     } while ( myErr == noErr );
  2398.  
  2399.     return( myErr );
  2400. }
  2401.  
  2402. #endif
  2403.  
  2404. void
  2405. display_error(OSErr err, int msg, char *file, int line)
  2406. {
  2407.     static Str32    errStr;
  2408.     static Str32    lineStr;
  2409.     static Str255    fileStr;
  2410.     static Str255    msgStr;
  2411.     
  2412.     strcpy((char *)fileStr, file);
  2413.     c2pstr((char *)fileStr);
  2414.     GetIndString(msgStr, string_error_codes, msg);
  2415.     NumToString(err, errStr);
  2416.     NumToString(line, lineStr);
  2417.     
  2418.     ParamText(msgStr, errStr, fileStr, lineStr);
  2419.     Alert(alert_error, NULL);
  2420. }
  2421.  
  2422. void
  2423. load_prefs(void)
  2424. {
  2425.     FSSpec                prefFileSpec;
  2426.     short                prefFileRef;
  2427.     short                saveResFile;
  2428.     bootx_prefs_handle    prefs;
  2429.     OSErr                err;
  2430.     short                itemType;
  2431.     Rect                itemBox;
  2432.     Handle                itemHandle;
  2433.     Handle                rsrc;
  2434.     
  2435.     err = locate_file(string_prefs_file_names, kPreferencesFolderType, &prefFileSpec);
  2436.     if (err != noErr)
  2437.         return;
  2438.     
  2439.     saveResFile = CurResFile();
  2440.     
  2441.     prefFileRef = FSpOpenResFile(&prefFileSpec, fsRdPerm);
  2442.     if (prefFileRef == -1)
  2443.         return;
  2444.     
  2445.     UseResFile(prefFileRef);
  2446.     
  2447.     rsrc = Get1Resource('L2CR', 0);
  2448.     if (rsrc)
  2449.     {
  2450.         if (GetHandleSize(rsrc) == 4)
  2451.         {
  2452.             g_L2CR_pref        = true;
  2453.             g_L2CR_value    = *((UInt32 *)(*rsrc));
  2454.         }
  2455.         ReleaseResource(rsrc);
  2456.     }
  2457.     
  2458.     prefs = (bootx_prefs_handle)Get1Resource('PREF', 128);
  2459.     if (prefs == NULL)
  2460.         goto bail_close;
  2461.     
  2462.     // Compare oldest compatible of prefs with version compiled with this code
  2463.     if ((**prefs).compatible_version > BOOTX_PREFS_VERSION)
  2464.         goto bail_release;
  2465.     
  2466.     HLock((Handle)prefs);
  2467.     
  2468.     g_current_choice    = (**prefs).boot_choice;
  2469.     g_use_ramdisk        = g_have_ramdisk ? (**prefs).use_ramdisk : false;
  2470.     g_video_of_only        = (**prefs).video_of_only;
  2471.     g_L2CR_set            = (**prefs).use_l2cr_settings && g_L2CR_pref;
  2472.     
  2473.     if (!g_boot_choices[g_current_choice][1])
  2474.         g_current_choice = boot_macos;
  2475.         
  2476.     GetDialogItem(g_dialog, field_kernel_args, &itemType, &itemHandle, &itemBox);
  2477.     if (itemHandle)
  2478.         SetDialogItemText(itemHandle, (**prefs).command_line);
  2479.  
  2480.     if (g_L2CR_available)
  2481.     {
  2482.         if (g_L2CR_pref)
  2483.             SetControlValue(g_set_L2CR_cntl, g_L2CR_set);
  2484.         else
  2485.             HiliteControl(g_set_L2CR_cntl, 255);
  2486.     }
  2487.     
  2488.     if ((**prefs).version >= 2)
  2489.     {
  2490.         GetDialogItem(g_dialog, field_root_device, &itemType, &itemHandle, &itemBox);
  2491.         if (itemHandle)
  2492.             SetDialogItemText(itemHandle, (**prefs).root_device);
  2493.     }
  2494.     if ((**prefs).version >= 4)
  2495.     {
  2496.         int i;
  2497.         
  2498.         for (i=0;i<g_kernel_items_count; i++)
  2499.             if (EqualString(g_kernel_items[i].file.name, (**prefs).kernel_name, false, false)) {
  2500.                 g_kernel_items_choice = i;
  2501.                 SetControlValue(g_kernel_menu, g_kernel_items[i].menu_item);
  2502.             }
  2503.     }
  2504.  
  2505.     SetControlValue(g_use_ramdisk_cntl, g_use_ramdisk);
  2506.     if (!g_have_ramdisk)
  2507.         HiliteControl(g_use_ramdisk_cntl, 255);
  2508.  
  2509.     SetControlValue(g_video_of_only_cntl, g_video_of_only);
  2510.     
  2511.     setup_default_buttons();
  2512.  
  2513. bail_release:
  2514.     HUnlock((Handle)prefs);
  2515.     ReleaseResource((Handle)prefs);
  2516. bail_close:
  2517.     CloseResFile(prefFileRef);
  2518.     
  2519.     UseResFile(saveResFile);
  2520. }
  2521.  
  2522. void
  2523. save_prefs(void)
  2524. {
  2525.     short                prefsVRefNum;
  2526.     long                prefsParID;
  2527.     static Str255        fileName;
  2528.     FSSpec                prefFileSpec;
  2529.     short                prefFileRef;
  2530.     short                saveResFile;
  2531.     bootx_prefs_handle    prefs;
  2532.     OSErr                err;
  2533.     short                itemType;
  2534.     Rect                itemBox;
  2535.     Handle                itemHandle;
  2536.     int                    i;
  2537.     
  2538.     // Build kernel FSSpec
  2539.     err = FindFolder(    kOnSystemDisk,
  2540.                         kPreferencesFolderType,
  2541.                         true,
  2542.                         &prefsVRefNum,
  2543.                         &prefsParID);
  2544.     if (err != noErr)
  2545.     {
  2546.         DEBUG_ERR(err, error_access_prefs);
  2547.         return;
  2548.     }
  2549.     GetIndString(fileName, string_prefs_file_names, 1);
  2550.     
  2551.     saveResFile = CurResFile();
  2552.  
  2553.     err = FSMakeFSSpec(    prefsVRefNum, prefsParID, fileName, &prefFileSpec);
  2554.     if (err == fnfErr)
  2555.     {
  2556.         FSpCreateResFile(&prefFileSpec, 'BooX', 'pref', smSystemScript);
  2557.         err = ResError();
  2558.     }
  2559.     if (err != noErr)
  2560.     {
  2561.         DEBUG_ERR(err, error_loadcreate_prefs);
  2562.         return;
  2563.     }
  2564.     
  2565.     prefFileRef = FSpOpenResFile(&prefFileSpec, fsWrPerm);
  2566.     if (prefFileRef == -1)
  2567.     {
  2568.         err = ResError();
  2569.         DEBUG_ERR(err, error_openwrite_prefs);
  2570.         return;
  2571.     }
  2572.     
  2573.     prefs = (bootx_prefs_handle)Get1Resource('PREF', 128);
  2574.     if (prefs == NULL)
  2575.     {
  2576.         prefs = (bootx_prefs_handle)NewHandle(sizeof(bootx_prefs));
  2577.         if (prefs == NULL)
  2578.         {
  2579.             err = MemError();
  2580.             DEBUG_ERR(err, error_alloc_prefs);
  2581.             goto bail_close;
  2582.         }
  2583.         AddResource((Handle)prefs, 'PREF', 128, "¥p");
  2584.         err = ResError();
  2585.         if (err != noErr)
  2586.         if (prefs == NULL)
  2587.         {
  2588.             DisposeHandle((Handle)prefs);
  2589.             DEBUG_ERR(err, error_add_prefs);
  2590.             goto bail_close;
  2591.         }
  2592.     } else
  2593.         SetHandleSize((Handle)prefs, sizeof(bootx_prefs));
  2594.  
  2595.     HLock((Handle)prefs);
  2596.     
  2597.     memset(*prefs, 0, sizeof(bootx_prefs));
  2598.     (**prefs).version                = BOOTX_PREFS_VERSION;
  2599.     (**prefs).compatible_version    = BOOTX_PREFS_COMPATIBLE_VERSION;
  2600.     (**prefs).boot_choice            = g_current_choice;
  2601.     (**prefs).use_ramdisk            = g_use_ramdisk;
  2602.     (**prefs).video_of_only            = g_video_of_only;
  2603.     (**prefs).use_l2cr_settings        = g_L2CR_set;
  2604.     
  2605.     GetDialogItem(g_dialog, field_kernel_args, &itemType, &itemHandle, &itemBox);
  2606.     if (itemHandle)
  2607.         GetDialogItemText(itemHandle, (**prefs).command_line);
  2608.     GetDialogItem(g_dialog, field_root_device, &itemType, &itemHandle, &itemBox);
  2609.     if (itemHandle)
  2610.         GetDialogItemText(itemHandle, (**prefs).root_device);
  2611.     
  2612.     for (i=0; i<g_kernel_items_count; i++)
  2613.     if (g_kernel_items[i].menu_item == GetControlValue(g_kernel_menu))
  2614.         pstrcpy((**prefs).kernel_name, g_kernel_items[i].file.name);
  2615.  
  2616.     HUnlock((Handle)prefs);
  2617.     ChangedResource((Handle)prefs);
  2618.     WriteResource((Handle)prefs);
  2619.     ReleaseResource((Handle)prefs);
  2620.     
  2621. bail_close:
  2622.     CloseResFile(prefFileRef);
  2623.     UseResFile(saveResFile);
  2624.     FlushVol(NULL, prefsVRefNum);
  2625. }
  2626.  
  2627.  
  2628. void
  2629. do_boot_mklinux(void)
  2630. {
  2631.     Handle     rsrc, patch;
  2632.     Str255    fileName;
  2633.     OSErr    err;
  2634.     FSSpec    prefFileSpec;
  2635.     short    prefFileRef, booterFileRef;
  2636.     short    prefsVRefNum;
  2637.     long    prefsParID;
  2638.     long    count;
  2639.         
  2640.     // Build fake MkLinux prefs file
  2641.     rsrc = Get1Resource('TEXT', text_mkboot_fake_prefs);
  2642.     if (rsrc == NULL)
  2643.     {
  2644.         DEBUG_ERR(ResError(), error_load_mk_text);
  2645.         return;
  2646.     }
  2647.     HNoPurge(rsrc);
  2648.     patch = Get1Resource('STR#', string_mkboot_patch);
  2649.     if (patch == NULL)
  2650.     {
  2651.         DEBUG_ERR(ResError(), error_load_mk_str);
  2652.         return;
  2653.     }
  2654.     HNoPurge(patch);
  2655.     DetachResource(patch);
  2656.     err = FindFolder(    kOnSystemDisk,
  2657.                         kPreferencesFolderType,
  2658.                         true,
  2659.                         &prefsVRefNum,
  2660.                         &prefsParID);
  2661.     if (err != noErr)
  2662.     {
  2663.         DEBUG_ERR(err, error_locate_mk_prefs);
  2664.         return;
  2665.     }
  2666.     GetIndString(fileName, string_mkboot_patch, 1);
  2667.     err = FSMakeFSSpec(prefsVRefNum, prefsParID, fileName, &prefFileSpec);
  2668.     if (err == fnfErr)
  2669.         err = FSpCreate(&prefFileSpec, 'ttxt', 'TEXT', smSystemScript);
  2670.     if (err != noErr)
  2671.     {
  2672.         DEBUG_ERR(err, error_open_mk_prefs);
  2673.         return;
  2674.     }
  2675.     err = FSpOpenDF(&prefFileSpec, fsWrPerm, &prefFileRef);
  2676.     if (err != noErr)
  2677.     {
  2678.         DEBUG_ERR(err, error_open_mk_prefs);
  2679.         return;
  2680.     }
  2681.     err = SetEOF(prefFileRef, count = GetHandleSize(rsrc));
  2682.     if (err != noErr)
  2683.     {
  2684.         DEBUG_ERR(err, error_write_mk_prefs);
  2685.         return;
  2686.     }
  2687.     HLock(rsrc);
  2688.     FSWrite(prefFileRef, &count, *rsrc);
  2689.     FSClose(prefFileRef);
  2690.     ReleaseResource(rsrc);
  2691.     
  2692.     // Open the booter
  2693.     booterFileRef = FSpOpenResFile(&g_mkboot_spec, fsRdPerm);
  2694.     if (booterFileRef == -1)
  2695.     {
  2696.         DEBUG_ERR(ResError(), error_open_mk_booter);
  2697.         return;
  2698.     }
  2699.     
  2700.     rsrc = Get1Resource('STR#', string_mkboot_patched);
  2701.     if (rsrc == NULL)
  2702.     {
  2703.         DEBUG_ERR(ResError(), error_bad_mk_booter);
  2704.         return;
  2705.     }
  2706.     HNoPurge(rsrc);
  2707.     SetHandleSize(rsrc, GetHandleSize(patch));
  2708.     BlockMoveData(*patch, *rsrc, GetHandleSize(patch));
  2709.  
  2710.     rsrc = Get1Resource('INIT', 0);
  2711.     HNoPurge(rsrc);
  2712.     HLock(rsrc);
  2713.     
  2714.     UseResFile(booterFileRef);
  2715.     CallUniversalProc((UniversalProcPtr)*rsrc, kPascalStackBased);    
  2716. }
  2717.  
  2718. Boolean
  2719. locate_mklinux(void)
  2720. {
  2721.     OSErr    err;
  2722.     
  2723.     // Lookup booter
  2724.     err = locate_file(string_mkboot_names, kSystemFolderType, &g_mkboot_spec);
  2725.     if (err == noErr)
  2726.         return true;
  2727.  
  2728.     err = locate_file(string_mkboot_names, kExtensionFolderType, &g_mkboot_spec);
  2729.     if (err == noErr)
  2730.         return true;
  2731.     
  2732.     return false;
  2733. }
  2734.  
  2735.  
  2736. #if BOOTX_LOG_MAP
  2737.  
  2738. static Boolean    s_log_opened    = false;
  2739. static short    s_log_file        = -1;
  2740.  
  2741. static void
  2742. open_log_file(void)
  2743. {
  2744.     FSSpec    file;
  2745.     OSErr    err;
  2746.     
  2747.     if (s_log_opened)
  2748.         return;
  2749.         
  2750.     err = FSMakeFSSpec(0, 0, "¥pbootx.log", &file);
  2751.     if (err == fnfErr)
  2752.         err = FSpCreate(&file, 'CWIE', 'TEXT', smSystemScript);
  2753.     if (err != noErr)
  2754.         return;        
  2755.     err = FSpOpenDF(&file, fsRdWrPerm, &s_log_file);
  2756.     if (err != noErr)
  2757.         return;
  2758.  
  2759.     SetFPos(s_log_file, fsFromLEOF, 0);
  2760.  
  2761.     s_log_opened = true;
  2762. }
  2763.  
  2764. static void
  2765. close_log_file(void)
  2766. {
  2767.     if (!s_log_opened)    
  2768.         return;
  2769.     
  2770.     FSClose(s_log_file);
  2771.     s_log_file = -1;
  2772.     s_log_opened = false;
  2773. }
  2774.  
  2775. static void
  2776. log_printf(const char *fmt, ...)
  2777. {
  2778.     static char        s_buffer[1024];
  2779.     va_list            args;
  2780.     long            len;
  2781.     
  2782.     if (!s_log_opened)    
  2783.         return;
  2784.  
  2785.     va_start(args, fmt);
  2786.     len = vsprintf(s_buffer, fmt, args);
  2787.     va_end(args);
  2788.  
  2789.     if (len)
  2790.         FSWrite(s_log_file, &len, s_buffer);
  2791. }
  2792.  
  2793.  
  2794. #endif